This commit is contained in:
Matt Raykowski 2010-07-14 12:13:37 -05:00
commit e3302e6844
17 changed files with 332 additions and 99 deletions

View file

@ -186,6 +186,9 @@ public:
/// Set the title of the NeL window /// Set the title of the NeL window
virtual void setWindowTitle(const ucstring &title)=0; virtual void setWindowTitle(const ucstring &title)=0;
/// Set icon(s) of the NeL window
virtual void setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)=0;
/// Set the position of the NeL window /// Set the position of the NeL window
virtual void setWindowPos(sint32 x, sint32 y)=0; virtual void setWindowPos(sint32 x, sint32 y)=0;

View file

@ -148,6 +148,9 @@ public:
/// Set the title of the NeL window /// Set the title of the NeL window
virtual void setWindowTitle(const ucstring &title); virtual void setWindowTitle(const ucstring &title);
/// Set icon(s) of the NeL window
virtual void setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps);
/// Set the position of the NeL window /// Set the position of the NeL window
virtual void setWindowPos(sint32 x, sint32 y); virtual void setWindowPos(sint32 x, sint32 y);

View file

@ -34,7 +34,7 @@ namespace NL3D {
template <> template <>
const char *CPSAttribMaker<NLMISC::CRGBA>::getType() { return "CRGBA"; } inline const char *CPSAttribMaker<NLMISC::CRGBA>::getType() { return "CRGBA"; }
// Depending on the driver, the format of colors in vertex buffer may change. We don't want to change the format for each data that is (dynamically) in vertex buffer, so // Depending on the driver, the format of colors in vertex buffer may change. We don't want to change the format for each data that is (dynamically) in vertex buffer, so

View file

@ -28,7 +28,7 @@
namespace NL3D { namespace NL3D {
template <> template <>
const char *CPSAttribMaker<float>::getType() { return "float"; } inline const char *CPSAttribMaker<float>::getType() { return "float"; }
/// these are some attribute makers for float /// these are some attribute makers for float
/// This is a float blender class. It just blend between 2 values /// This is a float blender class. It just blend between 2 values

View file

@ -26,7 +26,7 @@
namespace NL3D { namespace NL3D {
template <> template <>
const char *CPSAttribMaker<uint32>::getType() { return "int32"; } inline const char *CPSAttribMaker<uint32>::getType() { return "int32"; }
/// these are some attribute makers for int /// these are some attribute makers for int

View file

@ -28,7 +28,7 @@
namespace NL3D { namespace NL3D {
template <> template <>
const char *CPSAttribMaker<CPlaneBasis>::getType() { return "CPlaneBasis";} inline const char *CPSAttribMaker<CPlaneBasis>::getType() { return "CPlaneBasis";}
/** these are some attribute makers for plane_basis /** these are some attribute makers for plane_basis
* This is a plane basis class. It just blend between 2 plane by linearly interpolating the normal * This is a plane basis class. It just blend between 2 plane by linearly interpolating the normal

View file

@ -186,6 +186,9 @@ public:
/// Set the title of the NeL window /// Set the title of the NeL window
virtual void setWindowTitle(const ucstring &title)=0; virtual void setWindowTitle(const ucstring &title)=0;
/// Set icon(s) of the NeL window
virtual void setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)=0;
/// Set the position of the NeL window /// Set the position of the NeL window
virtual void setWindowPos(sint32 x, sint32 y)=0; virtual void setWindowPos(sint32 x, sint32 y)=0;

View file

@ -621,6 +621,10 @@ public:
void getDibData(uint8*& extractData); void getDibData(uint8*& extractData);
#ifdef NL_OS_WINDOWS
HICON getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false) const;
#endif
CBitmap& operator= (const CBitmap& from) CBitmap& operator= (const CBitmap& from)
{ {
if (&from == this) if (&from == this)

View file

@ -34,7 +34,7 @@ namespace NL3D
{ {
// *************************************************************************** // ***************************************************************************
const uint32 IDriver::InterfaceVersion = 0x67; // changed window pos from uint32 to sint32 const uint32 IDriver::InterfaceVersion = 0x68; // added setWindowIcon
// *************************************************************************** // ***************************************************************************
IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" ) IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" )

View file

@ -1712,6 +1712,10 @@ bool CDriverD3D::release()
if (_HWnd) if (_HWnd)
{ {
// make sure window icons are deleted
std::vector<NLMISC::CBitmap> bitmaps;
setWindowIcon(bitmaps);
if (_DestroyWindow) if (_DestroyWindow)
DestroyWindow (_HWnd); DestroyWindow (_HWnd);
_HWnd = NULL; _HWnd = NULL;
@ -2177,6 +2181,73 @@ void CDriverD3D::setWindowTitle(const ucstring &title)
SetWindowTextW(_HWnd,(WCHAR*)title.c_str()); SetWindowTextW(_HWnd,(WCHAR*)title.c_str());
} }
// ***************************************************************************
void CDriverD3D::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
{
if (!_HWnd)
return;
static HICON winIconBig = NULL;
static HICON winIconSmall = NULL;
if (winIconBig)
{
DestroyIcon(winIconBig);
winIconBig = NULL;
}
if (winIconSmall)
{
DestroyIcon(winIconSmall);
winIconSmall = NULL;
}
sint smallIndex = -1;
uint smallWidth = GetSystemMetrics(SM_CXSMICON);
uint smallHeight = GetSystemMetrics(SM_CYSMICON);
sint bigIndex = -1;
uint bigWidth = GetSystemMetrics(SM_CXICON);
uint bigHeight = GetSystemMetrics(SM_CYICON);
// find icons with the exact size
for(uint i = 0; i < bitmaps.size(); ++i)
{
if (smallIndex == -1 && bitmaps[i].getWidth() == smallWidth && bitmaps[i].getHeight() == smallHeight)
smallIndex = i;
if (bigIndex == -1 && bitmaps[i].getWidth() == bigWidth && bitmaps[i].getHeight() == bigHeight)
bigIndex = i;
}
// find icons with taller size (we will resize them)
for(uint i = 0; i < bitmaps.size(); ++i)
{
if (smallIndex == -1 && bitmaps[i].getWidth() >= smallWidth && bitmaps[i].getHeight() >= smallHeight)
smallIndex = i;
if (bigIndex == -1 && bitmaps[i].getWidth() >= bigWidth && bitmaps[i].getHeight() >= bigHeight)
bigIndex = i;
}
if (smallIndex > -1)
winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32);
if (bigIndex > -1)
winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32);
if (winIconBig)
{
SendMessage(_HWnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall);
SendMessage(_HWnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconBig);
}
else
{
SendMessage(_HWnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall);
SendMessage(_HWnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconSmall);
}
}
// *************************************************************************** // ***************************************************************************
void CDriverD3D::setWindowPos(sint32 x, sint32 y) void CDriverD3D::setWindowPos(sint32 x, sint32 y)
{ {

View file

@ -759,6 +759,9 @@ public:
/// Set the title of the NeL window /// Set the title of the NeL window
virtual void setWindowTitle(const ucstring &title); virtual void setWindowTitle(const ucstring &title);
/// Set icon(s) of the NeL window
virtual void setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps);
/// Set the position of the NeL window /// Set the position of the NeL window
virtual void setWindowPos(sint32 x, sint32 y); virtual void setWindowPos(sint32 x, sint32 y);

View file

@ -294,10 +294,13 @@ public:
virtual void beginDialogMode(); virtual void beginDialogMode();
virtual void endDialogMode(); virtual void endDialogMode();
/// Set the title of the NeL window /// Set title of the NeL window
virtual void setWindowTitle(const ucstring &title); virtual void setWindowTitle(const ucstring &title);
/// Set the position of the NeL window /// Set icon(s) of the NeL window
virtual void setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps);
/// Set position of the NeL window
virtual void setWindowPos(sint32 x, sint32 y); virtual void setWindowPos(sint32 x, sint32 y);
/// Show or hide the NeL window /// Show or hide the NeL window

View file

@ -35,11 +35,13 @@
# ifdef XRANDR # ifdef XRANDR
# include <X11/extensions/Xrandr.h> # include <X11/extensions/Xrandr.h>
# endif # endif
# include <X11/Xatom.h>
#endif // NL_OS_UNIX #endif // NL_OS_UNIX
#include "nel/misc/mouse_device.h" #include "nel/misc/mouse_device.h"
#include "nel/misc/di_event_emitter.h" #include "nel/misc/di_event_emitter.h"
#include "nel/3d/u_driver.h" #include "nel/3d/u_driver.h"
#include "nel/misc/file.h"
using namespace std; using namespace std;
using namespace NLMISC; using namespace NLMISC;
@ -296,6 +298,123 @@ bool CDriverGL::unInit()
return true; return true;
} }
void CDriverGL::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
{
if (_win == EmptyWindow)
return;
#if defined(NL_OS_WINDOWS)
static HICON winIconBig = NULL;
static HICON winIconSmall = NULL;
if (winIconBig)
{
DestroyIcon(winIconBig);
winIconBig = NULL;
}
if (winIconSmall)
{
DestroyIcon(winIconSmall);
winIconSmall = NULL;
}
sint smallIndex = -1;
uint smallWidth = GetSystemMetrics(SM_CXSMICON);
uint smallHeight = GetSystemMetrics(SM_CYSMICON);
sint bigIndex = -1;
uint bigWidth = GetSystemMetrics(SM_CXICON);
uint bigHeight = GetSystemMetrics(SM_CYICON);
// find icons with the exact size
for(uint i = 0; i < bitmaps.size(); ++i)
{
if (smallIndex == -1 && bitmaps[i].getWidth() == smallWidth && bitmaps[i].getHeight() == smallHeight)
smallIndex = i;
if (bigIndex == -1 && bitmaps[i].getWidth() == bigWidth && bitmaps[i].getHeight() == bigHeight)
bigIndex = i;
}
// find icons with taller size (we will resize them)
for(uint i = 0; i < bitmaps.size(); ++i)
{
if (smallIndex == -1 && bitmaps[i].getWidth() >= smallWidth && bitmaps[i].getHeight() >= smallHeight)
smallIndex = i;
if (bigIndex == -1 && bitmaps[i].getWidth() >= bigWidth && bitmaps[i].getHeight() >= bigHeight)
bigIndex = i;
}
if (smallIndex > -1)
winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32);
if (bigIndex > -1)
winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32);
if (winIconBig)
{
SendMessage(_win, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall);
SendMessage(_win, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconBig);
}
else
{
SendMessage(_win, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall);
SendMessage(_win, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconSmall);
}
#elif defined(NL_OS_MAC)
// nothing to do
#elif defined(NL_OS_UNIX)
std::vector<long> icon_data;
if (!bitmaps.empty())
{
// process each bitmap
for(uint i = 0; i < bitmaps.size(); ++i)
{
// get bitmap width and height
uint width = bitmaps[i].getWidth();
uint height = bitmaps[i].getHeight();
// icon_data position for bitmap
uint pos = (uint)icon_data.size();
// extend icon_data size for bitmap
icon_data.resize(pos + 2 + width*height);
// set bitmap width and height
icon_data[pos++] = width;
icon_data[pos++] = height;
// convert RGBA to ARGB
CObjectVector<uint8> pixels = bitmaps[i].getPixels();
for(uint j = 0; j < pixels.size(); j+=4)
icon_data[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24;
}
}
Atom _NET_WM_ICON = XInternAtom(_dpy, "_NET_WM_ICON", False);
if (!icon_data.empty())
{
// change window icon
XChangeProperty(_dpy, _win, _NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) &icon_data[0], icon_data.size());
}
else
{
// delete window icon if no bitmap is available
XDeleteProperty(_dpy, _win, _NET_WM_ICON);
}
#endif // NL_OS_WINDOWS
}
// -------------------------------------------------- // --------------------------------------------------
bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool resizeable) throw(EBadDisplay) bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool resizeable) throw(EBadDisplay)
{ {
@ -967,7 +1086,7 @@ bool CDriverGL::setScreenMode(const GfxMode &mode)
if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{ {
nlwarning("Fullscreen mode switch failed"); nlwarning("3D: Fullscreen mode switch failed");
return false; return false;
} }
@ -1135,6 +1254,10 @@ bool CDriverGL::destroyWindow()
{ {
H_AUTO_OGL(CDriverGL_destroyWindow) H_AUTO_OGL(CDriverGL_destroyWindow)
// make sure window icons are deleted
std::vector<NLMISC::CBitmap> bitmaps;
setWindowIcon(bitmaps);
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
// Then delete. // Then delete.

View file

@ -809,49 +809,46 @@ void submitEvents(NLMISC::CEventServer& server,
continue; continue;
} }
// convert the modifiers for nel to pass them with the events
NLMISC::TKeyButton modifiers =
modifierFlagsToNelKeyButton([event modifierFlags]);
switch(event.type) switch(event.type)
{ {
case NSLeftMouseDown: case NSLeftMouseDown:
{ {
/*
TODO modifiers with mouse events
*/
server.postEvent(new NLMISC::CEventMouseDown( server.postEvent(new NLMISC::CEventMouseDown(
mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter)); mouseX, mouseY,
(NLMISC::TMouseButton)(NLMISC::leftButton | modifiers),
eventEmitter));
} }
break; break;
case NSLeftMouseUp: case NSLeftMouseUp:
{ {
/*
TODO modifiers with mouse events
*/
server.postEvent(new NLMISC::CEventMouseUp( server.postEvent(new NLMISC::CEventMouseUp(
mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter)); mouseX, mouseY,
(NLMISC::TMouseButton)(NLMISC::leftButton | modifiers),
eventEmitter));
break; break;
} }
case NSRightMouseDown: case NSRightMouseDown:
{ {
/*
TODO modifiers with mouse events
*/
server.postEvent(new NLMISC::CEventMouseDown( server.postEvent(new NLMISC::CEventMouseDown(
mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter)); mouseX, mouseY,
(NLMISC::TMouseButton)(NLMISC::rightButton | modifiers),
eventEmitter));
break; break;
} }
case NSRightMouseUp: case NSRightMouseUp:
{ {
/*
TODO modifiers with mouse events
*/
server.postEvent(new NLMISC::CEventMouseUp( server.postEvent(new NLMISC::CEventMouseUp(
mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter)); mouseX, mouseY,
(NLMISC::TMouseButton)(NLMISC::rightButton | modifiers),
eventEmitter));
break; break;
} }
case NSMouseMoved: case NSMouseMoved:
{ {
/*
TODO modifiers with mouse events
*/
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
@ -861,17 +858,14 @@ void submitEvents(NLMISC::CEventServer& server,
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(
(NLMISC::TMouseButton)0 /* modifiers */, eventEmitter); mouseX, mouseY, (NLMISC::TMouseButton)modifiers, eventEmitter);
server.postEvent(nelEvent); server.postEvent(nelEvent);
break; break;
} }
case NSLeftMouseDragged: case NSLeftMouseDragged:
{ {
/*
TODO modifiers with mouse events
*/
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
@ -882,16 +876,14 @@ void submitEvents(NLMISC::CEventServer& server,
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
NLMISC::leftButton /* modifiers */, eventEmitter); (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers),
eventEmitter);
server.postEvent(nelEvent); server.postEvent(nelEvent);
break; break;
} }
case NSRightMouseDragged: case NSRightMouseDragged:
{ {
/*
TODO modifiers with mouse events
*/
NLMISC::CEvent* nelEvent; NLMISC::CEvent* nelEvent;
// when emulating raw mode, send the delta in a CGDMouseMove event // when emulating raw mode, send the delta in a CGDMouseMove event
@ -902,7 +894,8 @@ void submitEvents(NLMISC::CEventServer& server,
// normally send position in a CEventMouseMove // normally send position in a CEventMouseMove
else else
nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY,
NLMISC::rightButton /* modifiers */, eventEmitter); (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers),
eventEmitter);
server.postEvent(nelEvent); server.postEvent(nelEvent);
break; break;
@ -951,12 +944,9 @@ void submitEvents(NLMISC::CEventServer& server,
case NSCursorUpdate:break; case NSCursorUpdate:break;
case NSScrollWheel: case NSScrollWheel:
{ {
/*
TODO modifiers with mouse events
*/
if(fabs(event.deltaY) > 0.1) if(fabs(event.deltaY) > 0.1)
server.postEvent(new NLMISC::CEventMouseWheel( server.postEvent(new NLMISC::CEventMouseWheel(
mouseX, mouseY, (NLMISC::TMouseButton)0 /* modifiers */, mouseX, mouseY, (NLMISC::TMouseButton)modifiers,
(event.deltaY > 0), eventEmitter)); (event.deltaY > 0), eventEmitter));
break; break;

View file

@ -332,6 +332,13 @@ void CDriverUser::setWindowTitle(const ucstring &title)
_Driver->setWindowTitle(title); _Driver->setWindowTitle(title);
} }
// ***************************************************************************
void CDriverUser::setWindowIcon(const std::vector<NLMISC::CBitmap> &bitmaps)
{
NL3D_HAUTO_UI_DRIVER;
_Driver->setWindowIcon(bitmaps);
}
// *************************************************************************** // ***************************************************************************
void CDriverUser::setWindowPos(sint32 x, sint32 y) void CDriverUser::setWindowPos(sint32 x, sint32 y)
{ {

View file

@ -1500,7 +1500,7 @@ uint32 CBitmap::getHeight(uint32 mipMap) const
/*-------------------------------------------------------------------*\ /*-------------------------------------------------------------------*\
getHeight getSize
\*-------------------------------------------------------------------*/ \*-------------------------------------------------------------------*/
uint32 CBitmap::getSize(uint32 numMipMap) const uint32 CBitmap::getSize(uint32 numMipMap) const
{ {
@ -4107,5 +4107,84 @@ void CBitmap::getDibData(uint8*& extractData)
} }
#ifdef NL_OS_WINDOWS
HICON CBitmap::getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) const
{
HICON result = NULL;
CBitmap src = *this;
// resample bitmap if necessary
if (_Width != iconWidth || _Height != iconHeight)
{
src.resample(iconWidth, iconHeight);
}
CBitmap colorBm;
colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
static volatile uint8 alphaThreshold = 127;
do
{
destColorPtr->modulateFromColor(*srcColorPtr, col);
std::swap(destColorPtr->R, destColorPtr->B);
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
//
HBITMAP colorHbm = NULL;
HBITMAP maskHbm = NULL;
//
if (iconDepth == 16)
{
std::vector<uint16> colorBm16(iconWidth * iconHeight);
const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0];
for (uint k = 0; k < colorBm16.size(); ++k)
{
colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8);
}
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]);
std::vector<uint8> bitMask((iconWidth * iconHeight + 7) / 8, 0);
for (uint k = 0;k < colorBm16.size(); ++k)
{
if (src32[k].A <= 120)
{
bitMask[k / 8] |= (0x80 >> (k & 7));
}
}
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]);
}
else
{
colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]);
}
ICONINFO iconInfo;
iconInfo.fIcon = cursor ? FALSE:TRUE;
iconInfo.xHotspot = (DWORD) hotSpotX;
iconInfo.yHotspot = (DWORD) hotSpotY;
iconInfo.hbmMask = maskHbm;
iconInfo.hbmColor = colorHbm;
if (colorHbm && maskHbm)
{
result = CreateIconIndirect(&iconInfo);
}
//
if (colorHbm) DeleteObject(colorHbm);
if (maskHbm) DeleteObject(maskHbm);
return result;
}
#endif
} // NLMISC } // NLMISC

View file

@ -370,7 +370,6 @@ HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot
uint mouseH = GetSystemMetrics(SM_CYCURSOR); uint mouseH = GetSystemMetrics(SM_CYCURSOR);
nlassert(src.getWidth() == mouseW); nlassert(src.getWidth() == mouseW);
nlassert(src.getHeight() == mouseH); nlassert(src.getHeight() == mouseH);
HICON result = 0;
CBitmap rotSrc = src; CBitmap rotSrc = src;
if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...) if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...)
switch(rot) switch(rot)
@ -380,62 +379,7 @@ HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot
case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break; case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break;
case 3: rotSrc.rot90CCW(); break; case 3: rotSrc.rot90CCW(); break;
} }
CBitmap colorBm; return rotSrc.getHICON(mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY, true);
colorBm.resize(mouseW, mouseH, CBitmap::RGBA);
const CRGBA *srcColorPtr = (CRGBA *) &(rotSrc.getPixels()[0]);
const CRGBA *srcColorPtrLast = srcColorPtr + (mouseW * mouseH);
CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]);
static volatile uint8 alphaThreshold = 127;
do
{
destColorPtr->modulateFromColor(*srcColorPtr, col);
std::swap(destColorPtr->R, destColorPtr->B);
++ srcColorPtr;
++ destColorPtr;
}
while (srcColorPtr != srcColorPtrLast);
//
HBITMAP colorHbm = 0;
HBITMAP maskHbm = 0;
//
if (_ColorDepth == ColorDepth16)
{
std::vector<uint16> colorBm16(colorBm.getWidth() * colorBm.getHeight());
const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0];
for (uint k = 0;k < colorBm16.size(); ++k)
{
colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8);
}
colorHbm = CreateBitmap(mouseW, mouseH, 1, 16, &colorBm16[0]);
std::vector<uint8> bitMask((colorBm.getWidth() * colorBm.getHeight() + 7) / 8, 0);
for (uint k = 0;k < colorBm16.size(); ++k)
{
if (src32[k].A <= 120)
{
bitMask[k / 8] |= (0x80 >> (k & 7));
}
}
maskHbm = CreateBitmap(mouseW, mouseH, 1, 1, &bitMask[0]);
}
else
{
colorHbm = CreateBitmap(mouseW, mouseH, 1, 32, &colorBm.getPixels(0)[0]);
maskHbm = CreateBitmap(mouseW, mouseH, 1, 32, &colorBm.getPixels(0)[0]);
}
ICONINFO iconInfo;
iconInfo.fIcon = FALSE;
iconInfo.xHotspot = (DWORD) hotSpotX;
iconInfo.yHotspot = (DWORD) hotSpotY;
iconInfo.hbmMask = maskHbm;
iconInfo.hbmColor = colorHbm;
if (colorHbm && maskHbm)
{
result = CreateIconIndirect(&iconInfo);
}
//
if (colorHbm) DeleteObject(colorHbm);
if (maskHbm) DeleteObject(maskHbm);
return result;
} }