зеркало из https://github.com/mozilla/pjs.git
Bug 502710 - Refactor the widget icon creation code r=jimm
--HG-- extra : rebase_source : 2f145f67bdc7d9f630970786a498fb5a411ad7d0
This commit is contained in:
Родитель
25bee23cf5
Коммит
7e7f6f7017
|
@ -1869,142 +1869,6 @@ NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Adjust cursor image data
|
||||
PRUint8* nsWindow::Data32BitTo1Bit(PRUint8* aImageData,
|
||||
PRUint32 aWidth, PRUint32 aHeight)
|
||||
{
|
||||
// We need (aWidth + 7) / 8 bytes plus zero-padding up to a multiple of
|
||||
// 4 bytes for each row (HBITMAP requirement). Bug 353553.
|
||||
PRUint32 outBpr = ((aWidth + 31) / 8) & ~3;
|
||||
|
||||
// Allocate and clear mask buffer
|
||||
PRUint8* outData = (PRUint8*)PR_Calloc(outBpr, aHeight);
|
||||
if (!outData)
|
||||
return NULL;
|
||||
|
||||
PRInt32 *imageRow = (PRInt32*)aImageData;
|
||||
for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
|
||||
PRUint8 *outRow = outData + curRow * outBpr;
|
||||
PRUint8 mask = 0x80;
|
||||
for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
|
||||
// Use sign bit to test for transparency, as alpha byte is highest byte
|
||||
if (*imageRow++ < 0)
|
||||
*outRow |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
if (!mask) {
|
||||
outRow ++;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
PRBool nsWindow::IsCursorTranslucencySupported()
|
||||
{
|
||||
#ifdef WINCE
|
||||
return PR_FALSE;
|
||||
#else
|
||||
static PRBool didCheck = PR_FALSE;
|
||||
static PRBool isSupported = PR_FALSE;
|
||||
if (!didCheck) {
|
||||
didCheck = PR_TRUE;
|
||||
// Cursor translucency is supported on Windows XP and newer
|
||||
isSupported = nsWindow::GetWindowsVersion() >= 0x501;
|
||||
}
|
||||
|
||||
return isSupported;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given image data to a HBITMAP. If the requested depth is
|
||||
* 32 bit and the OS supports translucency, a bitmap with an alpha channel
|
||||
* will be returned.
|
||||
*
|
||||
* @param aImageData The image data to convert. Must use the format accepted
|
||||
* by CreateDIBitmap.
|
||||
* @param aWidth With of the bitmap, in pixels.
|
||||
* @param aHeight Height of the image, in pixels.
|
||||
* @param aDepth Image depth, in bits. Should be one of 1, 24 and 32.
|
||||
*
|
||||
* @return The HBITMAP representing the image. Caller should call
|
||||
* DeleteObject when done with the bitmap.
|
||||
* On failure, NULL will be returned.
|
||||
*/
|
||||
HBITMAP nsWindow::DataToBitmap(PRUint8* aImageData,
|
||||
PRUint32 aWidth,
|
||||
PRUint32 aHeight,
|
||||
PRUint32 aDepth)
|
||||
{
|
||||
#ifndef WINCE
|
||||
HDC dc = ::GetDC(NULL);
|
||||
|
||||
if (aDepth == 32 && IsCursorTranslucencySupported()) {
|
||||
// Alpha channel. We need the new header.
|
||||
BITMAPV4HEADER head = { 0 };
|
||||
head.bV4Size = sizeof(head);
|
||||
head.bV4Width = aWidth;
|
||||
head.bV4Height = aHeight;
|
||||
head.bV4Planes = 1;
|
||||
head.bV4BitCount = aDepth;
|
||||
head.bV4V4Compression = BI_BITFIELDS;
|
||||
head.bV4SizeImage = 0; // Uncompressed
|
||||
head.bV4XPelsPerMeter = 0;
|
||||
head.bV4YPelsPerMeter = 0;
|
||||
head.bV4ClrUsed = 0;
|
||||
head.bV4ClrImportant = 0;
|
||||
|
||||
head.bV4RedMask = 0x00FF0000;
|
||||
head.bV4GreenMask = 0x0000FF00;
|
||||
head.bV4BlueMask = 0x000000FF;
|
||||
head.bV4AlphaMask = 0xFF000000;
|
||||
|
||||
HBITMAP bmp = ::CreateDIBitmap(dc,
|
||||
reinterpret_cast<CONST BITMAPINFOHEADER*>(&head),
|
||||
CBM_INIT,
|
||||
aImageData,
|
||||
reinterpret_cast<CONST BITMAPINFO*>(&head),
|
||||
DIB_RGB_COLORS);
|
||||
::ReleaseDC(NULL, dc);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
char reserved_space[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2];
|
||||
BITMAPINFOHEADER& head = *(BITMAPINFOHEADER*)reserved_space;
|
||||
|
||||
head.biSize = sizeof(BITMAPINFOHEADER);
|
||||
head.biWidth = aWidth;
|
||||
head.biHeight = aHeight;
|
||||
head.biPlanes = 1;
|
||||
head.biBitCount = (WORD)aDepth;
|
||||
head.biCompression = BI_RGB;
|
||||
head.biSizeImage = 0; // Uncompressed
|
||||
head.biXPelsPerMeter = 0;
|
||||
head.biYPelsPerMeter = 0;
|
||||
head.biClrUsed = 0;
|
||||
head.biClrImportant = 0;
|
||||
|
||||
BITMAPINFO& bi = *(BITMAPINFO*)reserved_space;
|
||||
|
||||
if (aDepth == 1) {
|
||||
RGBQUAD black = { 0, 0, 0, 0 };
|
||||
RGBQUAD white = { 255, 255, 255, 0 };
|
||||
|
||||
bi.bmiColors[0] = white;
|
||||
bi.bmiColors[1] = black;
|
||||
}
|
||||
|
||||
HBITMAP bmp = ::CreateDIBitmap(dc, &head, CBM_INIT, aImageData, &bi, DIB_RGB_COLORS);
|
||||
::ReleaseDC(NULL, dc);
|
||||
return bmp;
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Setting the actual cursor
|
||||
NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
|
||||
PRUint32 aHotspotX, PRUint32 aHotspotY)
|
||||
|
@ -2014,14 +1878,14 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the image data
|
||||
nsRefPtr<gfxImageSurface> frame;
|
||||
aCursor->CopyCurrentFrame(getter_AddRefs(frame));
|
||||
if (!frame)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
PRInt32 width;
|
||||
PRInt32 height;
|
||||
|
||||
PRInt32 width = frame->Width();
|
||||
PRInt32 height = frame->Height();
|
||||
nsresult rv;
|
||||
rv = aCursor->GetWidth(&width);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aCursor->GetHeight(&height);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Reject cursors greater than 128 pixels in either direction, to prevent
|
||||
// spoofing.
|
||||
|
@ -2030,30 +1894,9 @@ NS_IMETHODIMP nsWindow::SetCursor(imgIContainer* aCursor,
|
|||
if (width > 128 || height > 128)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
PRUint8 *data = frame->Data();
|
||||
|
||||
HBITMAP bmp = DataToBitmap(data, width, -height, 32);
|
||||
PRUint8* a1data = Data32BitTo1Bit(data, width, height);
|
||||
if (!a1data) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HBITMAP mbmp = DataToBitmap(a1data, width, -height, 1);
|
||||
PR_Free(a1data);
|
||||
|
||||
ICONINFO info = {0};
|
||||
info.fIcon = FALSE;
|
||||
info.xHotspot = aHotspotX;
|
||||
info.yHotspot = aHotspotY;
|
||||
info.hbmMask = mbmp;
|
||||
info.hbmColor = bmp;
|
||||
|
||||
HCURSOR cursor = ::CreateIconIndirect(&info);
|
||||
::DeleteObject(mbmp);
|
||||
::DeleteObject(bmp);
|
||||
if (cursor == NULL) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
HCURSOR cursor;
|
||||
rv = nsWindowGfx::CreateIcon(aCursor, PR_TRUE, aHotspotX, aHotspotY, &cursor);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCursor = nsCursor(-1);
|
||||
::SetCursor(cursor);
|
||||
|
|
|
@ -374,13 +374,6 @@ private:
|
|||
protected:
|
||||
#endif // MOZ_XUL
|
||||
|
||||
/**
|
||||
* Cursor helpers
|
||||
*/
|
||||
static PRUint8* Data32BitTo1Bit(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
|
||||
static PRBool IsCursorTranslucencySupported();
|
||||
static HBITMAP DataToBitmap(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
|
||||
|
||||
/**
|
||||
* Misc.
|
||||
*/
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "gfxContext.h"
|
||||
#include "nsIRenderingContext.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "prmem.h"
|
||||
|
||||
#ifndef WINCE
|
||||
#include "nsUXThemeData.h"
|
||||
|
@ -643,6 +644,202 @@ DDRAW_FAILED:
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult nsWindowGfx::CreateIcon(imgIContainer *aContainer,
|
||||
PRBool aIsCursor,
|
||||
PRUint32 aHotspotX,
|
||||
PRUint32 aHotspotY,
|
||||
HICON *aIcon) {
|
||||
|
||||
nsresult rv;
|
||||
PRInt32 maxWidth = GetSystemMetrics(SM_CXICON);
|
||||
PRInt32 maxHeight = GetSystemMetrics(SM_CYICON);
|
||||
|
||||
if (!maxWidth || !maxHeight)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRUint32 nFrames;
|
||||
rv = aContainer->GetNumFrames(&nFrames);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!nFrames)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// Get the image data
|
||||
nsRefPtr<gfxImageSurface> frame;
|
||||
aContainer->CopyCurrentFrame(getter_AddRefs(frame));
|
||||
if (!frame)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
PRUint8 *data = frame->Data();
|
||||
|
||||
PRInt32 width = frame->Width();
|
||||
PRInt32 height = frame->Height();
|
||||
|
||||
if (width > maxWidth || height > maxHeight)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
HBITMAP bmp = DataToBitmap(data, width, -height, 32);
|
||||
PRUint8* a1data = Data32BitTo1Bit(data, width, height);
|
||||
if (!a1data) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HBITMAP mbmp = DataToBitmap(a1data, width, -height, 1);
|
||||
PR_Free(a1data);
|
||||
|
||||
ICONINFO info = {0};
|
||||
info.fIcon = !aIsCursor;
|
||||
info.xHotspot = aHotspotX;
|
||||
info.yHotspot = aHotspotY;
|
||||
info.hbmMask = mbmp;
|
||||
info.hbmColor = bmp;
|
||||
|
||||
HCURSOR icon = ::CreateIconIndirect(&info);
|
||||
::DeleteObject(mbmp);
|
||||
::DeleteObject(bmp);
|
||||
if (!icon)
|
||||
return NS_ERROR_FAILURE;
|
||||
*aIcon = icon;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Adjust cursor image data
|
||||
PRUint8* nsWindowGfx::Data32BitTo1Bit(PRUint8* aImageData,
|
||||
PRUint32 aWidth, PRUint32 aHeight)
|
||||
{
|
||||
// We need (aWidth + 7) / 8 bytes plus zero-padding up to a multiple of
|
||||
// 4 bytes for each row (HBITMAP requirement). Bug 353553.
|
||||
PRUint32 outBpr = ((aWidth + 31) / 8) & ~3;
|
||||
|
||||
// Allocate and clear mask buffer
|
||||
PRUint8* outData = (PRUint8*)PR_Calloc(outBpr, aHeight);
|
||||
if (!outData)
|
||||
return NULL;
|
||||
|
||||
PRInt32 *imageRow = (PRInt32*)aImageData;
|
||||
for (PRUint32 curRow = 0; curRow < aHeight; curRow++) {
|
||||
PRUint8 *outRow = outData + curRow * outBpr;
|
||||
PRUint8 mask = 0x80;
|
||||
for (PRUint32 curCol = 0; curCol < aWidth; curCol++) {
|
||||
// Use sign bit to test for transparency, as alpha byte is highest byte
|
||||
if (*imageRow++ < 0)
|
||||
*outRow |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
if (!mask) {
|
||||
outRow ++;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outData;
|
||||
}
|
||||
|
||||
PRBool nsWindowGfx::IsCursorTranslucencySupported()
|
||||
{
|
||||
#ifdef WINCE
|
||||
return PR_FALSE;
|
||||
#else
|
||||
static PRBool didCheck = PR_FALSE;
|
||||
static PRBool isSupported = PR_FALSE;
|
||||
if (!didCheck) {
|
||||
didCheck = PR_TRUE;
|
||||
// Cursor translucency is supported on Windows XP and newer
|
||||
isSupported = nsWindow::GetWindowsVersion() >= 0x501;
|
||||
}
|
||||
|
||||
return isSupported;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given image data to a HBITMAP. If the requested depth is
|
||||
* 32 bit and the OS supports translucency, a bitmap with an alpha channel
|
||||
* will be returned.
|
||||
*
|
||||
* @param aImageData The image data to convert. Must use the format accepted
|
||||
* by CreateDIBitmap.
|
||||
* @param aWidth With of the bitmap, in pixels.
|
||||
* @param aHeight Height of the image, in pixels.
|
||||
* @param aDepth Image depth, in bits. Should be one of 1, 24 and 32.
|
||||
*
|
||||
* @return The HBITMAP representing the image. Caller should call
|
||||
* DeleteObject when done with the bitmap.
|
||||
* On failure, NULL will be returned.
|
||||
*/
|
||||
HBITMAP nsWindowGfx::DataToBitmap(PRUint8* aImageData,
|
||||
PRUint32 aWidth,
|
||||
PRUint32 aHeight,
|
||||
PRUint32 aDepth)
|
||||
{
|
||||
#ifndef WINCE
|
||||
HDC dc = ::GetDC(NULL);
|
||||
|
||||
if (aDepth == 32 && IsCursorTranslucencySupported()) {
|
||||
// Alpha channel. We need the new header.
|
||||
BITMAPV4HEADER head = { 0 };
|
||||
head.bV4Size = sizeof(head);
|
||||
head.bV4Width = aWidth;
|
||||
head.bV4Height = aHeight;
|
||||
head.bV4Planes = 1;
|
||||
head.bV4BitCount = aDepth;
|
||||
head.bV4V4Compression = BI_BITFIELDS;
|
||||
head.bV4SizeImage = 0; // Uncompressed
|
||||
head.bV4XPelsPerMeter = 0;
|
||||
head.bV4YPelsPerMeter = 0;
|
||||
head.bV4ClrUsed = 0;
|
||||
head.bV4ClrImportant = 0;
|
||||
|
||||
head.bV4RedMask = 0x00FF0000;
|
||||
head.bV4GreenMask = 0x0000FF00;
|
||||
head.bV4BlueMask = 0x000000FF;
|
||||
head.bV4AlphaMask = 0xFF000000;
|
||||
|
||||
HBITMAP bmp = ::CreateDIBitmap(dc,
|
||||
reinterpret_cast<CONST BITMAPINFOHEADER*>(&head),
|
||||
CBM_INIT,
|
||||
aImageData,
|
||||
reinterpret_cast<CONST BITMAPINFO*>(&head),
|
||||
DIB_RGB_COLORS);
|
||||
::ReleaseDC(NULL, dc);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
char reserved_space[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2];
|
||||
BITMAPINFOHEADER& head = *(BITMAPINFOHEADER*)reserved_space;
|
||||
|
||||
head.biSize = sizeof(BITMAPINFOHEADER);
|
||||
head.biWidth = aWidth;
|
||||
head.biHeight = aHeight;
|
||||
head.biPlanes = 1;
|
||||
head.biBitCount = (WORD)aDepth;
|
||||
head.biCompression = BI_RGB;
|
||||
head.biSizeImage = 0; // Uncompressed
|
||||
head.biXPelsPerMeter = 0;
|
||||
head.biYPelsPerMeter = 0;
|
||||
head.biClrUsed = 0;
|
||||
head.biClrImportant = 0;
|
||||
|
||||
BITMAPINFO& bi = *(BITMAPINFO*)reserved_space;
|
||||
|
||||
if (aDepth == 1) {
|
||||
RGBQUAD black = { 0, 0, 0, 0 };
|
||||
RGBQUAD white = { 255, 255, 255, 0 };
|
||||
|
||||
bi.bmiColors[0] = white;
|
||||
bi.bmiColors[1] = black;
|
||||
}
|
||||
|
||||
HBITMAP bmp = ::CreateDIBitmap(dc, &head, CBM_INIT, aImageData, &bi, DIB_RGB_COLORS);
|
||||
::ReleaseDC(NULL, dc);
|
||||
return bmp;
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Windows Mobile Special image/direct draw painting fun
|
||||
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||
PRBool nsWindow::OnPaintImageDDraw16()
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
*/
|
||||
|
||||
#include "nsWindow.h"
|
||||
#include <imgIContainer.h>
|
||||
|
||||
// This isn't ideal, we should figure out how to export
|
||||
// the #defines here; need this to figure out if we have
|
||||
|
@ -62,6 +63,16 @@ public:
|
|||
#if defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||
static PRBool InitDDraw();
|
||||
#endif // defined(CAIRO_HAS_DDRAW_SURFACE)
|
||||
|
||||
static nsresult CreateIcon(imgIContainer *aContainer, PRBool aIsCursor, PRUint32 aHotspotX, PRUint32 aHotspotY, HICON *aIcon);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Cursor helpers
|
||||
*/
|
||||
static PRUint8* Data32BitTo1Bit(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight);
|
||||
static PRBool IsCursorTranslucencySupported();
|
||||
static HBITMAP DataToBitmap(PRUint8* aImageData, PRUint32 aWidth, PRUint32 aHeight, PRUint32 aDepth);
|
||||
};
|
||||
|
||||
#endif // WindowGfx_h__
|
||||
#endif // WindowGfx_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче