Commit b3d25fbe authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move NtUserDrawIconEx implementation from user32.

parent c24326b8
......@@ -103,11 +103,6 @@ static void release_icon_frame( struct cursoricon_object *obj, struct cursoricon
}
}
static UINT get_icon_steps( struct cursoricon_object *obj )
{
return obj->is_ani ? obj->ani.num_steps : 1;
}
static void free_icon_frame( struct cursoricon_frame *frame )
{
if (frame->color) DeleteObject( frame->color );
......@@ -1667,7 +1662,7 @@ BOOL WINAPI DestroyCursor( HCURSOR hCursor )
*/
BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
{
return DrawIconEx( hdc, x, y, hIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );
return NtUserDrawIconEx( hdc, x, y, hIcon, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE );
}
/***********************************************************************
......@@ -1984,173 +1979,6 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
return ret;
}
/******************************************************************************
* DrawIconEx (USER32.@) Draws an icon or cursor on device context
*
* NOTES
* Why is this using SM_CXICON instead of SM_CXCURSOR?
*
* PARAMS
* hdc [I] Handle to device context
* x0 [I] X coordinate of upper left corner
* y0 [I] Y coordinate of upper left corner
* hIcon [I] Handle to icon to draw
* cxWidth [I] Width of icon
* cyWidth [I] Height of icon
* istep [I] Index of frame in animated cursor
* hbr [I] Handle to background brush
* flags [I] Icon-drawing flags
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
INT cxWidth, INT cyWidth, UINT istep,
HBRUSH hbr, UINT flags )
{
struct cursoricon_frame *frame;
struct cursoricon_object *ptr;
HDC hdc_dest, hMemDC;
BOOL result = FALSE, DoOffscreen;
HBITMAP hB_off = 0;
COLORREF oldFg, oldBg;
INT x, y, nStretchMode;
TRACE_(icon)("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n",
hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags );
if (!(ptr = get_icon_ptr( hIcon ))) return FALSE;
if (istep >= get_icon_steps( ptr ))
{
TRACE_(icon)("Stepped past end of animated frames=%d\n", istep);
release_user_handle_ptr( ptr );
return FALSE;
}
if (!(frame = get_icon_frame( ptr, istep )))
{
FIXME_(icon)("Error retrieving icon frame %d\n", istep);
release_user_handle_ptr( ptr );
return FALSE;
}
if (!(hMemDC = CreateCompatibleDC( hdc )))
{
release_icon_frame( ptr, frame );
release_user_handle_ptr( ptr );
return FALSE;
}
if (flags & DI_NOMIRROR)
FIXME_(icon)("Ignoring flag DI_NOMIRROR\n");
/* Calculate the size of the destination image. */
if (cxWidth == 0)
{
if (flags & DI_DEFAULTSIZE)
cxWidth = GetSystemMetrics (SM_CXICON);
else
cxWidth = frame->width;
}
if (cyWidth == 0)
{
if (flags & DI_DEFAULTSIZE)
cyWidth = GetSystemMetrics (SM_CYICON);
else
cyWidth = frame->height;
}
DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
if (DoOffscreen) {
RECT r;
SetRect(&r, 0, 0, cxWidth, cxWidth);
if (!(hdc_dest = CreateCompatibleDC(hdc))) goto failed;
if (!(hB_off = CreateCompatibleBitmap(hdc, cxWidth, cyWidth)))
{
DeleteDC( hdc_dest );
goto failed;
}
SelectObject(hdc_dest, hB_off);
FillRect(hdc_dest, &r, hbr);
x = y = 0;
}
else
{
hdc_dest = hdc;
x = x0;
y = y0;
}
nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
oldFg = SetTextColor( hdc, RGB(0,0,0) );
oldBg = SetBkColor( hdc, RGB(255,255,255) );
if (frame->alpha && (flags & DI_IMAGE))
{
BOOL alpha_blend = TRUE;
if (GetObjectType( hdc_dest ) == OBJ_MEMDC)
{
BITMAP bm;
HBITMAP bmp = GetCurrentObject( hdc_dest, OBJ_BITMAP );
alpha_blend = GetObjectW( bmp, sizeof(bm), &bm ) && bm.bmBitsPixel > 8;
}
if (alpha_blend)
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
SelectObject( hMemDC, frame->alpha );
if (GdiAlphaBlend( hdc_dest, x, y, cxWidth, cyWidth, hMemDC,
0, 0, frame->width, frame->height,
pixelblend )) goto done;
}
}
if (flags & DI_MASK)
{
DWORD rop = (flags & DI_IMAGE) ? SRCAND : SRCCOPY;
SelectObject( hMemDC, frame->mask );
StretchBlt( hdc_dest, x, y, cxWidth, cyWidth,
hMemDC, 0, 0, frame->width, frame->height, rop );
}
if (flags & DI_IMAGE)
{
if (frame->color)
{
DWORD rop = (flags & DI_MASK) ? SRCINVERT : SRCCOPY;
SelectObject( hMemDC, frame->color );
StretchBlt( hdc_dest, x, y, cxWidth, cyWidth,
hMemDC, 0, 0, frame->width, frame->height, rop );
}
else
{
DWORD rop = (flags & DI_MASK) ? SRCINVERT : SRCCOPY;
SelectObject( hMemDC, frame->mask );
StretchBlt( hdc_dest, x, y, cxWidth, cyWidth,
hMemDC, 0, frame->height, frame->width,
frame->height, rop );
}
}
done:
if (DoOffscreen) BitBlt( hdc, x0, y0, cxWidth, cyWidth, hdc_dest, 0, 0, SRCCOPY );
SetTextColor( hdc, oldFg );
SetBkColor( hdc, oldBg );
SetStretchBltMode (hdc, nStretchMode);
result = TRUE;
if (hdc_dest != hdc) DeleteDC( hdc_dest );
if (hB_off) DeleteObject(hB_off);
failed:
DeleteDC( hMemDC );
release_icon_frame( ptr, frame );
release_user_handle_ptr( ptr );
return result;
}
/***********************************************************************
* DIB_FixColorsToLoadflags
*
......
......@@ -875,7 +875,7 @@ static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
hOldBitmap = SelectObject(hMemDC, hBitmap);
SetMapMode(hMemDC, MM_TEXT);
DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
NtUserDrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, GetSysColorBrush(COLOR_MENU), DI_NORMAL);
SelectObject (hMemDC, hOldBitmap);
DeleteDC(hMemDC);
ReleaseDC(hChild, hdc);
......
......@@ -243,8 +243,8 @@ BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
if (!hIcon) hIcon = NC_IconForWindow(hwnd);
DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
NtUserDrawIconEx( hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL );
rc.left = pt.x + GetSystemMetrics( SM_CXSMICON );
}
......@@ -686,9 +686,9 @@ BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
NC_GetInsideRect( hwnd, COORDS_WINDOW, &rect, style, ex_style );
pt.x = rect.left + 2;
pt.y = rect.top + (GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYSMICON)) / 2;
DrawIconEx (hdc, pt.x, pt.y, hIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
NtUserDrawIconEx( hdc, pt.x, pt.y, hIcon,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL );
}
return (hIcon != 0);
}
......
......@@ -728,8 +728,8 @@ static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
else
iconRect = rc;
FillRect( hdc, &rc, hbrush );
DrawIconEx( hdc, iconRect.left, iconRect.top, hIcon, iconRect.right - iconRect.left,
iconRect.bottom - iconRect.top, 0, NULL, DI_NORMAL );
NtUserDrawIconEx( hdc, iconRect.left, iconRect.top, hIcon, iconRect.right - iconRect.left,
iconRect.bottom - iconRect.top, 0, NULL, DI_NORMAL );
}
}
......
......@@ -1543,7 +1543,7 @@ static BOOL UITOOLS_DrawStateJam( HDC hdc, UINT opcode, DRAWSTATEPROC func, LPAR
return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags);
case DST_ICON:
return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, 0, 0, 0, NULL, DI_NORMAL);
return NtUserDrawIconEx(hdc, rc->left, rc->top, (HICON)lp, 0, 0, 0, NULL, DI_NORMAL);
case DST_BITMAP:
memdc = CreateCompatibleDC(hdc);
......
......@@ -192,7 +192,7 @@
@ stub DrawFrame
@ stdcall DrawFrameControl(long ptr long long)
@ stdcall DrawIcon(long long long long)
@ stdcall DrawIconEx(long long long long long long long long long)
@ stdcall DrawIconEx(long long long long long long long long long) NtUserDrawIconEx
@ stdcall DrawMenuBar(long)
@ stdcall DrawMenuBarTemp(long long ptr long long)
@ stdcall DrawStateA(long long ptr long long long long long long long)
......
......@@ -29,12 +29,13 @@
#endif
#include <assert.h>
#include "win32u_private.h"
#include "ntgdi_private.h"
#include "ntuser_private.h"
#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
WINE_DECLARE_DEBUG_CHANNEL(icon);
static struct list icon_cache = LIST_INIT( icon_cache );
......@@ -592,3 +593,143 @@ BOOL WINAPI NtUserGetIconInfo( HICON icon, ICONINFO *info, UNICODE_STRING *modul
release_user_handle_ptr( obj );
return ret;
}
/******************************************************************************
* NtUserDrawIconEx (win32u.@)
*/
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT step, HBRUSH brush, UINT flags )
{
struct cursoricon_object *obj;
HBITMAP offscreen_bitmap = 0;
HDC hdc_dest, mem_dc;
COLORREF old_fg, old_bg;
INT x, y, nStretchMode;
BOOL result = FALSE;
TRACE_(icon)( "(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,step=%d,br=%p,flags=0x%08x)\n",
hdc, x0, y0, icon, width, height, step, brush, flags );
if (!(obj = get_icon_frame_ptr( icon, step )))
{
FIXME_(icon)("Error retrieving icon frame %d\n", step);
return FALSE;
}
if (!(mem_dc = NtGdiCreateCompatibleDC( hdc )))
{
release_user_handle_ptr( obj );
return FALSE;
}
if (flags & DI_NOMIRROR)
FIXME_(icon)("Ignoring flag DI_NOMIRROR\n");
/* Calculate the size of the destination image. */
if (width == 0)
{
if (flags & DI_DEFAULTSIZE)
width = get_system_metrics( SM_CXICON );
else
width = obj->frame.width;
}
if (height == 0)
{
if (flags & DI_DEFAULTSIZE)
height = get_system_metrics( SM_CYICON );
else
height = obj->frame.height;
}
if (get_gdi_object_type( brush ) == NTGDI_OBJ_BRUSH)
{
HBRUSH prev_brush;
RECT r;
SetRect(&r, 0, 0, width, width);
if (!(hdc_dest = NtGdiCreateCompatibleDC(hdc))) goto failed;
if (!(offscreen_bitmap = NtGdiCreateCompatibleBitmap(hdc, width, height)))
{
NtGdiDeleteObjectApp( hdc_dest );
goto failed;
}
NtGdiSelectBitmap( hdc_dest, offscreen_bitmap );
prev_brush = NtGdiSelectBrush( hdc_dest, brush );
NtGdiPatBlt( hdc_dest, r.left, r.top, r.right - r.left, r.bottom - r.top, PATCOPY );
if (prev_brush) NtGdiSelectBrush( hdc_dest, prev_brush );
x = y = 0;
}
else
{
hdc_dest = hdc;
x = x0;
y = y0;
}
nStretchMode = set_stretch_blt_mode( hdc, STRETCH_DELETESCANS );
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, RGB(0,0,0), &old_fg );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, RGB(255,255,255), &old_bg );
if (obj->frame.alpha && (flags & DI_IMAGE))
{
BOOL alpha_blend = TRUE;
if (get_gdi_object_type( hdc_dest ) == NTGDI_OBJ_MEMDC)
{
BITMAP bm;
HBITMAP bmp = NtGdiGetDCObject( hdc_dest, NTGDI_OBJ_SURF );
alpha_blend = NtGdiExtGetObjectW( bmp, sizeof(bm), &bm ) && bm.bmBitsPixel > 8;
}
if (alpha_blend)
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
NtGdiSelectBitmap( mem_dc, obj->frame.alpha );
if (NtGdiAlphaBlend( hdc_dest, x, y, width, height, mem_dc,
0, 0, obj->frame.width, obj->frame.height,
pixelblend, 0 )) goto done;
}
}
if (flags & DI_MASK)
{
DWORD rop = (flags & DI_IMAGE) ? SRCAND : SRCCOPY;
NtGdiSelectBitmap( mem_dc, obj->frame.mask );
NtGdiStretchBlt( hdc_dest, x, y, width, height,
mem_dc, 0, 0, obj->frame.width, obj->frame.height, rop, 0 );
}
if (flags & DI_IMAGE)
{
if (obj->frame.color)
{
DWORD rop = (flags & DI_MASK) ? SRCINVERT : SRCCOPY;
NtGdiSelectBitmap( mem_dc, obj->frame.color );
NtGdiStretchBlt( hdc_dest, x, y, width, height,
mem_dc, 0, 0, obj->frame.width, obj->frame.height, rop, 0 );
}
else
{
DWORD rop = (flags & DI_MASK) ? SRCINVERT : SRCCOPY;
NtGdiSelectBitmap( mem_dc, obj->frame.mask );
NtGdiStretchBlt( hdc_dest, x, y, width, height,
mem_dc, 0, obj->frame.height, obj->frame.width,
obj->frame.height, rop, 0 );
}
}
done:
if (offscreen_bitmap) NtGdiBitBlt( hdc, x0, y0, width, height, hdc_dest, 0, 0, SRCCOPY, 0, 0 );
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, old_fg, NULL );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, old_bg, NULL );
nStretchMode = set_stretch_blt_mode( hdc, nStretchMode );
result = TRUE;
if (hdc_dest != hdc) NtGdiDeleteObjectApp( hdc_dest );
if (offscreen_bitmap) NtGdiDeleteObjectApp( offscreen_bitmap );
failed:
NtGdiDeleteObjectApp( mem_dc );
release_user_handle_ptr( obj );
return result;
}
......@@ -891,6 +891,18 @@ static BOOL set_graphics_mode( DC *dc, int mode )
}
DWORD set_stretch_blt_mode( HDC hdc, DWORD mode )
{
DWORD ret;
DC *dc;
if (!(dc = get_dc_ptr( hdc ))) return 0;
ret = dc->attr->stretch_blt_mode;
dc->attr->stretch_blt_mode = mode;
release_dc_ptr( dc );
return ret;
}
/***********************************************************************
* NtGdiGetAndSetDCDword (win32u.@)
*/
......
......@@ -1157,6 +1157,7 @@ static struct unix_funcs unix_funcs =
NtUserClipCursor,
NtUserCountClipboardFormats,
NtUserDestroyCursor,
NtUserDrawIconEx,
NtUserEnumDisplayDevices,
NtUserEnumDisplayMonitors,
NtUserEnumDisplaySettings,
......
......@@ -171,6 +171,7 @@ extern DC *alloc_dc_ptr( DWORD magic ) DECLSPEC_HIDDEN;
extern void free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN;
extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN;
extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN;
extern DWORD set_stretch_blt_mode( HDC hdc, DWORD mode ) DECLSPEC_HIDDEN;
extern void update_dc( DC *dc ) DECLSPEC_HIDDEN;
extern void DC_InitDC( DC * dc ) DECLSPEC_HIDDEN;
extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN;
......
......@@ -850,7 +850,7 @@
@ stub NtUserDrawAnimatedRects
@ stub NtUserDrawCaption
@ stub NtUserDrawCaptionTemp
@ stub NtUserDrawIconEx
@ stdcall NtUserDrawIconEx(long long long long long long long long long)
@ stub NtUserDrawMenuBarTemp
@ stub NtUserDwmGetRemoteSessionOcclusionEvent
@ stub NtUserDwmGetRemoteSessionOcclusionState
......
......@@ -191,6 +191,8 @@ struct unix_funcs
BOOL (WINAPI *pNtUserClipCursor)( const RECT *rect );
INT (WINAPI *pNtUserCountClipboardFormats)(void);
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
NTSTATUS (WINAPI *pNtUserEnumDisplayDevices)( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags );
BOOL (WINAPI *pNtUserEnumDisplayMonitors)( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
......
......@@ -744,6 +744,13 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg )
return unix_funcs->pNtUserDestroyCursor( cursor, arg );
}
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserDrawIconEx( hdc, x0, y0, icon, width, height, istep, hbr, flags );
}
NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags )
{
......
......@@ -186,6 +186,8 @@ HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *d
HWINSTA WINAPI NtUserCreateWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK mask, ULONG arg3,
ULONG arg4, ULONG arg5, ULONG arg6, ULONG arg7 );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags );
BOOL WINAPI NtUserEnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment