300 lines
8.9 KiB
C++
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
|