cef/libcef/browser_webkit_glue_win.cc

300 lines
8.9 KiB
C++

// Copyright (c) 2008 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <atlcore.h>
#include <atlbase.h>
#include <commdlg.h>
#include "base/compiler_specific.h"
#include "third_party/WebKit/Source/WebCore/config.h"
MSVC_PUSH_WARNING_LEVEL(0);
#include "PlatformContextSkia.h"
MSVC_POP_WARNING();
#include "browser_webkit_glue.h"
#undef LOG
#include "base/logging.h"
#include "base/path_service.h"
#include "base/win/resource_util.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/gdi_util.h"
#include "webkit/glue/webkit_glue.h"
using WebKit::WebRect;
using WebKit::WebSize;
using WebKit::WebView;
namespace webkit_glue {
base::StringPiece GetRawDataResource(HMODULE module, int resource_id) {
void* data_ptr;
size_t data_size;
return base::win::GetDataResourceFromModule(module, resource_id, &data_ptr,
&data_size)
? base::StringPiece(static_cast<char*>(data_ptr), data_size)
: base::StringPiece();
}
base::StringPiece GetDataResource(int resource_id) {
base::StringPiece piece;
FilePath file_path;
HMODULE hModule = NULL;
// Try to load the resource from the DLL.
if (PathService::Get(base::FILE_MODULE, &file_path))
hModule = ::GetModuleHandle(file_path.value().c_str());
if(!hModule)
hModule = ::GetModuleHandle(NULL);
piece = GetRawDataResource(hModule, resource_id);
// Try to load the resource from the resource pack.
if (piece.empty())
piece = ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id);
DCHECK(!piece.empty()) << "Resource "<<resource_id<<" could not be loaded";
return piece;
}
bool EnsureFontLoaded(HFONT font) {
return true;
}
void CaptureWebViewBitmap(HWND mainWnd, WebView* webview, HBITMAP& bitmap,
SIZE& size)
{
WebKit::WebSize webSize = webview->size();
size.cx = webSize.width;
size.cy = webSize.height;
skia::PlatformCanvas canvas(size.cx, size.cy, true);
canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
WebCore::PlatformContextSkia context(&canvas);
WebKit::WebRect rect(0, 0, size.cx, size.cy);
webview->layout();
webview->paint(&canvas, rect);
HDC hRefDC = GetDC(mainWnd);
HDC hDC = CreateCompatibleDC(hRefDC);
bitmap = CreateCompatibleBitmap(hRefDC, size.cx, size.cy);
DCHECK(bitmap != NULL);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, bitmap);
// Create a BMP v4 header that we can serialize.
BITMAPV4HEADER bitmap_header;
gfx::CreateBitmapV4Header(size.cx, size.cy, &bitmap_header);
const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
SkAutoLockPixels src_lock(src_bmp);
int retval = StretchDIBits(hDC,
0,
0,
size.cx, size.cy,
0, 0,
size.cx, size.cy,
src_bmp.getPixels(),
reinterpret_cast<BITMAPINFO*>(&bitmap_header),
DIB_RGB_COLORS,
SRCCOPY);
DCHECK(retval != GDI_ERROR);
SelectObject(hDC, hOldBmp);
DeleteDC(hDC);
ReleaseDC(mainWnd, hRefDC);
}
static PBITMAPINFO BmpCreateInfo(HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Retrieve the bitmap color format, width, and height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) {
NOTREACHED();
return NULL;
}
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1) {
cClrBits = 1;
} else if (cClrBits <= 4) {
cClrBits = 4;
} else if (cClrBits <= 8) {
cClrBits = 8;
} else if (cClrBits <= 16) {
cClrBits = 16;
} else if (cClrBits <= 24) {
cClrBits = 24;
} else {
cClrBits = 32;
}
// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)
if (cClrBits != 24) {
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits));
} else { // There is no RGBQUAD array for the 24-bit-per-pixel format.
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
}
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24) {
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
}
// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
// For Windows NT, the width must be DWORD aligned unless
// the bitmap is RLE compressed. This example shows this.
// For Windows 95/98/Me, the width must be WORD aligned unless the
// bitmap is RLE compressed.
pbmi->bmiHeader.biSizeImage =
((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi->bmiHeader.biHeight;
// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
static BOOL BmpSaveFile(LPCTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP,
HDC hDC, LPBYTE lpBits = NULL)
{
HANDLE hf = INVALID_HANDLE_VALUE; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;
BOOL ret = FALSE;
BOOL bitsAlloc = FALSE;
pbih = (PBITMAPINFOHEADER) pbi;
if(!lpBits) {
// The bits have not been provided, so retrieve from the bitmap file
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits) {
// Memory could not be allocated
NOTREACHED();
return FALSE;
}
bitsAlloc = TRUE;
// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,
DIB_RGB_COLORS)) {
NOTREACHED();
goto end;
}
}
// Create the bitmap file.
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE) {
// Could not create the bitmap file
NOTREACHED();
goto end;
}
hdr.bfType = 0x4d42; // 0x42 = "B", 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the bitmap file.
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, NULL)) {
// Could not write bitmap file header to file
NOTREACHED();
goto end;
}
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, NULL)) {
// Could not write bitmap info header to file
NOTREACHED();
goto end;
}
// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) {
// Could not write bitmap data to file
NOTREACHED();
goto end;
}
ret = TRUE;
end:
// Close the bitmap file.
if(hf != INVALID_HANDLE_VALUE) {
CloseHandle(hf);
if(!ret)
DeleteFile(pszFile);
}
if(bitsAlloc)
{
// Free memory.
GlobalFree((HGLOBAL)lpBits);
}
return ret;
}
BOOL SaveBitmapToFile(HBITMAP hBmp, HDC hDC, LPCTSTR file, LPBYTE lpBits)
{
PBITMAPINFO pbmi = BmpCreateInfo(hBmp);
BOOL ret = FALSE;
if(pbmi) {
ret = BmpSaveFile(file, pbmi, hBmp, hDC, lpBits);
LocalFree(pbmi);
}
return ret;
}
} // namespace webkit_glue