/******************************************************************************************* * Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER. */ static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info ) { if (!info) return FALSE; if (info->biSize == sizeof(BITMAPCOREHEADER)) { const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info; dst->biWidth = core->bcWidth; dst->biHeight = core->bcHeight; dst->biPlanes = core->bcPlanes; dst->biBitCount = core->bcBitCount; dst->biCompression = BI_RGB; dst->biXPelsPerMeter = 0; dst->biYPelsPerMeter = 0; dst->biClrUsed = 0; dst->biClrImportant = 0; } else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */ { *dst = *info; } else { WARN( "(%u): unknown/wrong size for header\n", info->biSize ); return FALSE; } dst->biSize = sizeof(*dst); if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS) dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst ); return TRUE; }
static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip ) { int i = 0; int left, right; int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight; HRGN run = NULL; BYTE skip, num, data; BYTE *out_bits, *in_bits = bits->ptr; *clip = NULL; assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 ); out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) ); *clip = CreateRectRgn( 0, 0, 0, 0 ); run = CreateRectRgn( 0, 0, 0, 0 ); if (!out_bits || !*clip || !run) goto fail; x = left = right = 0; y = height - 1; while (i < info->bmiHeader.biSizeImage - 1) { num = in_bits[i]; data = in_bits[i + 1]; i += 2; if (num) { if (x + num > width) num = width - x; if (num) { BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y ); if (info->bmiHeader.biBitCount == 8) memset( out_ptr, s, num ); else { if(x & 1) { s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0); *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f); out_ptr++; x++; num--; } /* this will write one too many if num is odd, but that doesn't matter */ if (num) memset( out_ptr, s, (num + 1) / 2 ); } } x += num; right = x; } else { if (data < 3)
DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src, BITMAPINFO *dst_info, struct bitblt_coords *dst, struct gdi_image_bits *bits, int mode ) { void *ptr; DWORD err; dst_info->bmiHeader.biWidth = dst->visrect.right - dst->visrect.left; dst_info->bmiHeader.biHeight = dst->visrect.bottom - dst->visrect.top; dst_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info ); if (src_info->bmiHeader.biHeight < 0) dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; if (!(ptr = HeapAlloc( GetProcessHeap(), 0, dst_info->bmiHeader.biSizeImage ))) return ERROR_OUTOFMEMORY; err = stretch_bitmapinfo( src_info, bits->ptr, src, dst_info, ptr, dst, mode ); if (bits->free) bits->free( bits ); bits->ptr = ptr; bits->is_copy = TRUE; bits->free = free_heap_bits; return err; }
INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) { DWORD size; METARECORD *mr; LOGBRUSH logbrush; BOOL r; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; switch(logbrush.lbStyle) { case BS_SOLID: case BS_NULL: case BS_HATCHED: { LOGBRUSH16 lb16; lb16.lbStyle = logbrush.lbStyle; lb16.lbColor = logbrush.lbColor; lb16.lbHatch = logbrush.lbHatch; size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; mr = HeapAlloc( GetProcessHeap(), 0, size ); mr->rdSize = size / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); break; } case BS_PATTERN: { char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; struct gdi_image_bits bits; COLORREF cref; if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done; if (src_info->bmiHeader.biBitCount != 1) { FIXME("Trying to store a colour pattern brush\n"); if (bits.free) bits.free( &bits ); goto done; } size = FIELD_OFFSET( METARECORD, rdParm[2] ) + FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage; if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) { if (bits.free) bits.free( &bits ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = BS_PATTERN; mr->rdParm[1] = DIB_RGB_COLORS; dst_info = (BITMAPINFO *)(mr->rdParm + 2); dst_info->bmiHeader = src_info->bmiHeader; dst_info->bmiHeader.biClrUsed = 0; cref = GetTextColor( dev->hdc ); dst_info->bmiColors[0].rgbRed = GetRValue(cref); dst_info->bmiColors[0].rgbGreen = GetGValue(cref); dst_info->bmiColors[0].rgbBlue = GetBValue(cref); dst_info->bmiColors[0].rgbReserved = 0; cref = GetBkColor( dev->hdc ); dst_info->bmiColors[1].rgbRed = GetRValue(cref); dst_info->bmiColors[1].rgbGreen = GetGValue(cref); dst_info->bmiColors[1].rgbBlue = GetBValue(cref); dst_info->bmiColors[1].rgbReserved = 0; /* always return a bottom-up DIB */ if (dst_info->bmiHeader.biHeight < 0) { int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount ); char *dst_ptr = (char *)&dst_info->bmiColors[2]; dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes ); } else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage ); if (bits.free) bits.free( &bits ); break; } case BS_DIBPATTERN: { BITMAPINFO *info; DWORD bmSize, biSize; info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = get_dib_image_size( info ); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(METARECORD) + biSize + bmSize + 2; mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); if (!mr) { GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); goto done; } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; *(mr->rdParm) = logbrush.lbStyle; *(mr->rdParm + 1) = LOWORD(logbrush.lbColor); memcpy(mr->rdParm + 2, info, biSize + bmSize); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); break; } default: FIXME("Unkonwn brush style %x\n", logbrush.lbStyle); return 0; } r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); HeapFree(GetProcessHeap(), 0, mr); if( !r ) return -1; done: return MFDRV_AddHandle( dev, hBrush ); }
/*********************************************************************** * create_surface */ struct window_surface *create_surface(macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha) { struct macdrv_window_surface *surface; struct macdrv_window_surface *old_mac_surface = get_mac_surface(old_surface); int width = rect->right - rect->left, height = rect->bottom - rect->top; DWORD *colors; pthread_mutexattr_t attr; int err; DWORD window_background; surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])); if (!surface) return NULL; err = pthread_mutexattr_init(&attr); if (!err) { err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); if (!err) err = pthread_mutex_init(&surface->mutex, &attr); pthread_mutexattr_destroy(&attr); } if (err) { HeapFree(GetProcessHeap(), 0, surface); return NULL; } surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; surface->info.bmiHeader.biHeight = height; /* bottom-up */ surface->info.bmiHeader.biPlanes = 1; surface->info.bmiHeader.biBitCount = 32; surface->info.bmiHeader.biSizeImage = get_dib_image_size(&surface->info); surface->info.bmiHeader.biCompression = BI_RGB; surface->info.bmiHeader.biClrUsed = 0; colors = (DWORD *)((char *)&surface->info + surface->info.bmiHeader.biSize); colors[0] = 0x00ff0000; colors[1] = 0x0000ff00; colors[2] = 0x000000ff; surface->header.funcs = &macdrv_surface_funcs; surface->header.rect = *rect; surface->header.ref = 1; surface->window = window; reset_bounds(&surface->bounds); if (old_mac_surface && old_mac_surface->drawn) { surface->drawn = CreateRectRgnIndirect(rect); OffsetRgn(surface->drawn, -rect->left, -rect->top); if (CombineRgn(surface->drawn, surface->drawn, old_mac_surface->drawn, RGN_AND) <= NULLREGION) { DeleteObject(surface->drawn); surface->drawn = 0; } } update_blit_data(surface); surface->use_alpha = use_alpha; surface->bits = HeapAlloc(GetProcessHeap(), 0, surface->info.bmiHeader.biSizeImage); if (!surface->bits) goto failed; window_background = macdrv_window_background_color(); memset_pattern4(surface->bits, &window_background, surface->info.bmiHeader.biSizeImage); TRACE("created %p for %p %s bits %p-%p\n", surface, window, wine_dbgstr_rect(rect), surface->bits, surface->bits + surface->info.bmiHeader.biSizeImage); return &surface->header; failed: macdrv_surface_destroy(&surface->header); return NULL; }
/*********************************************************************** * EMFDRV_CreateBrushIndirect */ DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) { DWORD index = 0; LOGBRUSH logbrush; if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0; switch (logbrush.lbStyle) { case BS_SOLID: case BS_HATCHED: case BS_NULL: { EMRCREATEBRUSHINDIRECT emr; emr.emr.iType = EMR_CREATEBRUSHINDIRECT; emr.emr.nSize = sizeof(emr); emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr.lb.lbStyle = logbrush.lbStyle; emr.lb.lbColor = logbrush.lbColor; emr.lb.lbHatch = logbrush.lbHatch; if(!EMFDRV_WriteRecord( dev, &emr.emr )) index = 0; } break; case BS_DIBPATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; DWORD bmSize, biSize, size; BITMAPINFO *info = GlobalLock( (HGLOBAL)logbrush.lbHatch ); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = get_dib_image_size( info ); biSize = bitmap_info_size(info, LOWORD(logbrush.lbColor)); size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) break; emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; emr->emr.nSize = size; emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); emr->iUsage = LOWORD(logbrush.lbColor); emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT); emr->cbBmi = biSize; emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize; emr->cbBits = bmSize; memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info, biSize + bmSize ); if(!EMFDRV_WriteRecord( dev, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); GlobalUnlock( (HGLOBAL)logbrush.lbHatch ); } break; case BS_PATTERN: { EMRCREATEDIBPATTERNBRUSHPT *emr; char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; struct gdi_image_bits bits; DWORD size; if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) break; if (src_info->bmiHeader.biBitCount != 1) { FIXME("Trying to create a color pattern brush\n"); if (bits.free) bits.free( &bits ); break; } /* FIXME: There is an extra DWORD written by native before the BMI. * Not sure what its meant to contain. */ size = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + sizeof(DWORD) + sizeof(BITMAPINFOHEADER) + src_info->bmiHeader.biSizeImage; emr = HeapAlloc( GetProcessHeap(), 0, size ); if(!emr) { if (bits.free) bits.free( &bits ); break; } dst_info = (BITMAPINFO *)((LPBYTE)(emr + 1) + sizeof(DWORD)); dst_info->bmiHeader = src_info->bmiHeader; memcpy( &dst_info->bmiHeader + 1, bits.ptr, dst_info->bmiHeader.biSizeImage ); if (bits.free) bits.free( &bits ); emr->emr.iType = EMR_CREATEMONOBRUSH; emr->emr.nSize = size; emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); /* Presumably to reduce the size of the written EMF, MS supports an * undocumented iUsage value of 2, indicating a mono bitmap without the * 8 byte 2 entry black/white palette. Stupidly, they could have saved * over 20 bytes more by also ignoring the BITMAPINFO fields that are * irrelevant/constant for monochrome bitmaps. * FIXME: It may be that the DIB functions themselves accept this value. */ emr->iUsage = DIB_PAL_MONO; emr->offBmi = (LPBYTE)dst_info - (LPBYTE)emr; emr->cbBmi = sizeof( BITMAPINFOHEADER ); emr->offBits = emr->offBmi + emr->cbBmi; emr->cbBits = dst_info->bmiHeader.biSizeImage; if(!EMFDRV_WriteRecord( dev, &emr->emr )) index = 0; HeapFree( GetProcessHeap(), 0, emr ); } break; default: FIXME("Unknown style %x\n", logbrush.lbStyle); break; } return index; }
BOOL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert, void * grad_array, ULONG ngrad, ULONG mode ) { DC *dc = get_nulldrv_dc( dev ); char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *info = (BITMAPINFO *)buffer; struct bitblt_coords src, dst; struct gdi_image_bits bits; unsigned int i; POINT *pts; BOOL ret = FALSE; DWORD err; HRGN rgn; if (!(pts = HeapAlloc( GetProcessHeap(), 0, nvert * sizeof(*pts) ))) return FALSE; for (i = 0; i < nvert; i++) { pts[i].x = vert_array[i].x; pts[i].y = vert_array[i].y; } LPtoDP( dev->hdc, pts, nvert ); /* compute bounding rect of all the rectangles/triangles */ reset_bounds( &dst.visrect ); for (i = 0; i < ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); i++) { ULONG v = ((ULONG *)grad_array)[i]; dst.visrect.left = min( dst.visrect.left, pts[v].x ); dst.visrect.top = min( dst.visrect.top, pts[v].y ); dst.visrect.right = max( dst.visrect.right, pts[v].x ); dst.visrect.bottom = max( dst.visrect.bottom, pts[v].y ); } dst.x = dst.visrect.left; dst.y = dst.visrect.top; dst.width = dst.visrect.right - dst.visrect.left; dst.height = dst.visrect.bottom - dst.visrect.top; if (!clip_visrect( dc, &dst.visrect, &dst.visrect )) goto done; /* query the bitmap format */ info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biPlanes = 1; info->bmiHeader.biBitCount = 0; info->bmiHeader.biCompression = BI_RGB; info->bmiHeader.biXPelsPerMeter = 0; info->bmiHeader.biYPelsPerMeter = 0; info->bmiHeader.biClrUsed = 0; info->bmiHeader.biClrImportant = 0; info->bmiHeader.biWidth = dst.visrect.right - dst.visrect.left; info->bmiHeader.biHeight = dst.visrect.bottom - dst.visrect.top; info->bmiHeader.biSizeImage = 0; dev = GET_DC_PHYSDEV( dc, pPutImage ); err = dev->funcs->pPutImage( dev, 0, info, NULL, NULL, NULL, 0 ); if (err && err != ERROR_BAD_FORMAT) goto done; info->bmiHeader.biSizeImage = get_dib_image_size( info ); if (!(bits.ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage ))) goto done; bits.is_copy = TRUE; bits.free = free_heap_bits; /* make src and points relative to the bitmap */ src = dst; src.x -= dst.visrect.left; src.y -= dst.visrect.top; offset_rect( &src.visrect, -dst.visrect.left, -dst.visrect.top ); for (i = 0; i < nvert; i++) { pts[i].x -= dst.visrect.left; pts[i].y -= dst.visrect.top; } rgn = CreateRectRgn( 0, 0, 0, 0 ); gradient_bitmapinfo( info, bits.ptr, vert_array, nvert, grad_array, ngrad, mode, pts, rgn ); OffsetRgn( rgn, dst.visrect.left, dst.visrect.top ); ret = !dev->funcs->pPutImage( dev, rgn, info, &bits, &src, &dst, SRCCOPY ); if (bits.free) bits.free( &bits ); DeleteObject( rgn ); done: HeapFree( GetProcessHeap(), 0, pts ); return ret; }
/*********************************************************************** * create_icon_from_bmi * * Create an icon from its BITMAPINFO. */ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname, HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height, UINT cFlag ) { DWORD size, color_size, mask_size; HBITMAP color = 0, mask = 0, alpha = 0; const void *color_bits, *mask_bits; BITMAPINFO *bmi_copy; BOOL ret = FALSE; BOOL do_stretch; HICON hObj = 0; HDC hdc = 0; /* Check bitmap header */ if (maxsize < sizeof(BITMAPCOREHEADER)) { return 0; } if (maxsize < bmi->bmiHeader.biSize) { WARN( "invalid header size %u\n", bmi->bmiHeader.biSize ); return 0; } if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || (bmi->bmiHeader.biCompression != BI_RGB && bmi->bmiHeader.biCompression != BI_BITFIELDS)) ) { WARN( "invalid bitmap header %u\n", bmi->bmiHeader.biSize ); return 0; } size = bitmap_info_size( bmi, DIB_RGB_COLORS ); color_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, bmi->bmiHeader.biBitCount ); mask_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, 1 ); if (size > maxsize || color_size > maxsize - size) { WARN( "truncated file %u < %u+%u+%u\n", maxsize, size, color_size, mask_size ); return 0; } if (mask_size > maxsize - size - color_size) mask_size = 0; /* no mask */ if (cFlag & LR_DEFAULTSIZE) { if (!width) width = GetSystemMetrics( bIcon ? SM_CXICON : SM_CXCURSOR ); if (!height) height = GetSystemMetrics( bIcon ? SM_CYICON : SM_CYCURSOR ); } else { if (!width) width = bmi->bmiHeader.biWidth; if (!height) height = bmi->bmiHeader.biHeight/2; } do_stretch = (bmi->bmiHeader.biHeight/2 != height) || (bmi->bmiHeader.biWidth != width); /* Scale the hotspot */ if (bIcon) { hotspot.x = width / 2; hotspot.y = height / 2; } else if (do_stretch) { hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth; hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biHeight / 2); } if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL ); if (!screen_dc) return 0; if (!(bmi_copy = (BITMAPINFO*)HeapAlloc( GetProcessHeap(), 0, max( size, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))) return 0; if (!(hdc = CreateCompatibleDC( 0 ))) goto done; memcpy( bmi_copy, bmi, size ); bmi_copy->bmiHeader.biHeight /= 2; color_bits = (const char*)bmi + size; mask_bits = (const char*)color_bits + color_size; alpha = 0; if (is_dib_monochrome( bmi )) { if (!(mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; color = 0; /* copy color data into second half of mask bitmap */ SelectObject( hdc, mask ); StretchDIBits( hdc, 0, height, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } else { if (!(mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done; if (!(color = CreateBitmap( width, height, GetDeviceCaps( screen_dc, PLANES ), GetDeviceCaps( screen_dc, BITSPIXEL ), NULL ))) { DeleteObject( mask ); goto done; } SelectObject( hdc, color ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, color_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); if (bmi_has_alpha( bmi_copy, color_bits )) alpha = create_alpha_bitmap(bmi_copy, color_bits ,width,height); /* convert info to monochrome to copy the mask */ bmi_copy->bmiHeader.biBitCount = 1; if (bmi_copy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) { RGBQUAD *rgb = bmi_copy->bmiColors; bmi_copy->bmiHeader.biClrUsed = bmi_copy->bmiHeader.biClrImportant = 2; rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; rgb[0].rgbReserved = rgb[1].rgbReserved = 0; } else { RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)bmi_copy) + 1); rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; } } if (mask_size) { SelectObject( hdc, mask ); StretchDIBits( hdc, 0, 0, width, height, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); } ret = TRUE; done: DeleteDC( hdc ); HeapFree( GetProcessHeap(), 0, bmi_copy ); if(ret) { ICONINFO iconInfo={0}; iconInfo.fIcon=bIcon; iconInfo.xHotspot=hotspot.x; iconInfo.yHotspot=hotspot.y; if(alpha) { iconInfo.hbmColor=alpha; iconInfo.hbmMask=mask; } else { iconInfo.hbmColor=color; iconInfo.hbmMask=mask; } hObj=CreateIconIndirect(&iconInfo); if(color) DeleteObject( color ); if(alpha) DeleteObject( alpha ); if(mask) DeleteObject( mask ); } return hObj; }