mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for transparency on Windows (issue #99).
- Enable the use of Skia instead of GDI for text rendering. - Add a new CefWindowInfo::m_bTransparentPainting member. - Add transparent popup window and off-screen rendering examples to cefclient. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@334 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
@ -4,9 +4,11 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "osrplugin.h"
|
||||
#include "cefclient.h"
|
||||
#include "client_popup_handler.h"
|
||||
#include "osrplugin.h"
|
||||
#include "resource.h"
|
||||
#include "resource_util.h"
|
||||
#include "string_util.h"
|
||||
#include "util.h"
|
||||
#include <gl/gl.h>
|
||||
@ -28,6 +30,12 @@ float g_spinY = 0.0f;
|
||||
int g_width = -1, g_height = -1;
|
||||
CefRefPtr<CefBrowser> g_offscreenBrowser;
|
||||
|
||||
// If set to true alpha transparency will be used.
|
||||
bool g_offscreenTransparent = false;
|
||||
|
||||
#define GL_IMAGE_FORMAT (g_offscreenTransparent?GL_RGBA:GL_RGB)
|
||||
#define GL_BYTE_COUNT (g_offscreenTransparent?4:3)
|
||||
|
||||
// Class holding pointers for the client plugin window.
|
||||
class ClientPlugin
|
||||
{
|
||||
@ -48,6 +56,7 @@ public:
|
||||
class ClientOSRHandler : public CefClient,
|
||||
public CefLifeSpanHandler,
|
||||
public CefLoadHandler,
|
||||
public CefRequestHandler,
|
||||
public CefDisplayHandler,
|
||||
public CefRenderHandler
|
||||
{
|
||||
@ -73,6 +82,8 @@ public:
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE
|
||||
{ return this; }
|
||||
virtual CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE
|
||||
@ -134,6 +145,27 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// CefRequestHandler methods
|
||||
|
||||
virtual bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefString& redirectUrl,
|
||||
CefRefPtr<CefStreamReader>& resourceStream,
|
||||
CefRefPtr<CefResponse> response,
|
||||
int loadFlags) OVERRIDE
|
||||
{
|
||||
REQUIRE_IO_THREAD();
|
||||
|
||||
std::string url = request->GetURL();
|
||||
if(url == "http://tests/transparency") {
|
||||
resourceStream = GetBinaryResourceReader(IDS_TRANSPARENCY);
|
||||
response->SetMimeType("text/html");
|
||||
response->SetStatus(200);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// CefDisplayHandler methods
|
||||
|
||||
virtual void OnNavStateChange(CefRefPtr<CefBrowser> browser,
|
||||
@ -254,32 +286,55 @@ public:
|
||||
REQUIRE_UI_THREAD();
|
||||
|
||||
wglMakeCurrent(plugin_->hDC, plugin_->hRC);
|
||||
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, g_textureID);
|
||||
|
||||
if (type == PET_VIEW) {
|
||||
// Paint the view.
|
||||
SetRGB(buffer, g_width, g_height, true);
|
||||
if (g_offscreenTransparent)
|
||||
SetRGBA(buffer, g_width, g_height, true);
|
||||
else
|
||||
SetRGB(buffer, g_width, g_height, true);
|
||||
|
||||
// Update the whole texture. This is done for simplicity instead of
|
||||
// updating just the dirty region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_width, g_height, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, view_buffer_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_width, g_height,
|
||||
GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE, view_buffer_);
|
||||
}
|
||||
|
||||
if(popup_rect_.width > 0) {
|
||||
if (type == PET_POPUP) {
|
||||
// Paint the popup.
|
||||
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
if (g_offscreenTransparent)
|
||||
SetRGBA(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
else
|
||||
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
|
||||
}
|
||||
|
||||
if (popup_buffer_) {
|
||||
// Update the popup region.
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
|
||||
g_height-popup_rect_.y-popup_rect_.height, popup_rect_.width,
|
||||
popup_rect_.height, GL_RGB, GL_UNSIGNED_BYTE, popup_buffer_);
|
||||
popup_rect_.height, GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE,
|
||||
popup_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||
@ -305,18 +360,10 @@ private:
|
||||
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
|
||||
}
|
||||
|
||||
// Set the contents of the RGB buffer.
|
||||
void SetRGB(const void* src, int width, int height, bool view)
|
||||
{
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Size the RGB buffer.
|
||||
void SetBufferSize(int width, int height, bool view)
|
||||
{
|
||||
int dst_size = width * height * 3;
|
||||
int dst_size = width * height * GL_BYTE_COUNT;
|
||||
|
||||
// Allocate a new buffer if necesary.
|
||||
if (view) {
|
||||
@ -336,6 +383,38 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGBA buffer.
|
||||
void SetRGBA(const void* src, int width, int height, bool view)
|
||||
{
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGBA((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGBA format and from upper-left to lower-left origin.
|
||||
static void ConvertToRGBA(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
{
|
||||
int sp = 0, dp = (height-1) * width * 4;
|
||||
for(int i = 0; i < height; i++) {
|
||||
for(int j = 0; j < width; j++, dp += 4, sp += 4) {
|
||||
dst[dp] = src[sp+2]; // R
|
||||
dst[dp+1] = src[sp+1]; // G
|
||||
dst[dp+2] = src[sp]; // B
|
||||
dst[dp+3] = src[sp+3]; // A
|
||||
}
|
||||
dp -= width * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the contents of the RGB buffer.
|
||||
void SetRGB(const void* src, int width, int height, bool view)
|
||||
{
|
||||
SetBufferSize(width, height, view);
|
||||
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
|
||||
static void ConvertToRGB(const unsigned char* src, unsigned char* dst,
|
||||
int width, int height)
|
||||
@ -392,10 +471,14 @@ void EnableGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
|
||||
wglMakeCurrent(*hDC, *hRC);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Necessary for non-power-of-2 textures to render correctly.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Alpha blending style.
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable GL.
|
||||
@ -424,6 +507,14 @@ void SizeGL(ClientPlugin* plugin, int width, int height)
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 0, width, height, 0.1, 100.0);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Delete the existing exture.
|
||||
if(g_textureID != -1)
|
||||
glDeleteTextures(1, &g_textureID);
|
||||
@ -435,12 +526,20 @@ void SizeGL(ClientPlugin* plugin, int width, int height)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Start with all white contents.
|
||||
int size = width * height * 3;
|
||||
int size = width * height * GL_BYTE_COUNT;
|
||||
unsigned char* buffer = new unsigned char[size];
|
||||
memset(buffer, 255, size);
|
||||
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||
GL_IMAGE_FORMAT, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
@ -468,21 +567,43 @@ void RenderGL(ClientPlugin* plugin)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
//glTranslatef(0.0f, 0.0f, -3.0f);
|
||||
|
||||
// Draw the background gradient.
|
||||
glPushAttrib(GL_ALL_ATTRIB_BITS);
|
||||
glBegin(GL_QUADS);
|
||||
glColor4f(1.0,0.0,0.0,1.0); // red
|
||||
glVertex2f(-1.0,-1.0);
|
||||
glVertex2f(1.0,-1.0);
|
||||
glColor4f(0.0,0.0,1.0,1.0); // blue
|
||||
glVertex2f(1.0, 1.0);
|
||||
glVertex2f(-1.0, 1.0);
|
||||
glEnd();
|
||||
glPopAttrib();
|
||||
|
||||
// Rotate the view based on the mouse spin.
|
||||
glRotatef(-g_spinX, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(-g_spinY, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
// Enable alpha blending.
|
||||
//glEnable(GL_BLEND);
|
||||
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
if (g_offscreenTransparent) {
|
||||
// Enable alpha blending.
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
// Enable 2D textures.
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Draw the facets with the texture.
|
||||
glBindTexture(GL_TEXTURE_2D, g_textureID);
|
||||
glInterleavedArrays(GL_T2F_V3F, 0, vertices);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
//glDisable(GL_BLEND);
|
||||
// Disable 2D textures.
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
if (g_offscreenTransparent) {
|
||||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
SwapBuffers(plugin->hDC);
|
||||
}
|
||||
@ -556,6 +677,8 @@ NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
|
||||
CefWindowInfo windowInfo;
|
||||
CefBrowserSettings settings;
|
||||
windowInfo.SetAsOffScreen(plugin->hWnd);
|
||||
if (g_offscreenTransparent)
|
||||
windowInfo.SetTransparentPainting(TRUE);
|
||||
CefBrowser::CreateBrowser(windowInfo, new ClientOSRHandler(plugin),
|
||||
"http://www.google.com", settings);
|
||||
}
|
||||
@ -774,4 +897,9 @@ CefRefPtr<CefBrowser> GetOffScreenBrowser()
|
||||
return g_offscreenBrowser;
|
||||
}
|
||||
|
||||
void SetOffScreenTransparent(bool transparent)
|
||||
{
|
||||
g_offscreenTransparent = transparent;
|
||||
}
|
||||
|
||||
#endif // OS_WIN
|
||||
|
Reference in New Issue
Block a user