in shell/browser/notifications/win/win32_desktop_notifications/toast.cc [68:198]
static HBITMAP StretchBitmap(HBITMAP bitmap, unsigned width, unsigned height) {
// We use StretchBlt for the scaling, but that discards the alpha channel.
// So we first create a separate grayscale bitmap from the alpha channel,
// scale that separately, and copy it back to the scaled color bitmap.
BITMAP bm;
if (!GetObject(bitmap, sizeof(bm), &bm))
return NULL;
if (width == 0 || height == 0)
return NULL;
HBITMAP result_bitmap = NULL;
HDC hdc_screen = GetDC(NULL);
HBITMAP alpha_src_bitmap;
{
BITMAPINFOHEADER bmi = {sizeof(BITMAPINFOHEADER)};
bmi.biWidth = bm.bmWidth;
bmi.biHeight = bm.bmHeight;
bmi.biPlanes = bm.bmPlanes;
bmi.biBitCount = bm.bmBitsPixel;
bmi.biCompression = BI_RGB;
void* alpha_src_bits;
alpha_src_bitmap =
CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
DIB_RGB_COLORS, &alpha_src_bits, NULL, 0);
if (alpha_src_bitmap) {
if (GetDIBits(hdc_screen, bitmap, 0, 0, 0,
reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS) &&
bmi.biSizeImage > 0 && (bmi.biSizeImage % 4) == 0) {
auto* buf = reinterpret_cast<BYTE*>(
_aligned_malloc(bmi.biSizeImage, sizeof(DWORD)));
if (buf) {
GetDIBits(hdc_screen, bitmap, 0, bm.bmHeight, buf,
reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS);
const DWORD* src = reinterpret_cast<DWORD*>(buf);
const DWORD* end = reinterpret_cast<DWORD*>(buf + bmi.biSizeImage);
BYTE* dest = reinterpret_cast<BYTE*>(alpha_src_bits);
for (; src != end; ++src, ++dest) {
BYTE a = *src >> 24;
*dest++ = a;
*dest++ = a;
*dest++ = a;
}
_aligned_free(buf);
}
}
}
}
if (alpha_src_bitmap) {
BITMAPINFOHEADER bmi = {sizeof(BITMAPINFOHEADER)};
bmi.biWidth = width;
bmi.biHeight = height;
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biCompression = BI_RGB;
void* color_bits;
auto* color_bitmap =
CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
DIB_RGB_COLORS, &color_bits, NULL, 0);
void* alpha_bits;
auto* alpha_bitmap =
CreateDIBSection(NULL, reinterpret_cast<BITMAPINFO*>(&bmi),
DIB_RGB_COLORS, &alpha_bits, NULL, 0);
HDC hdc = CreateCompatibleDC(NULL);
HDC hdc_src = CreateCompatibleDC(NULL);
if (color_bitmap && alpha_bitmap && hdc && hdc_src) {
SetStretchBltMode(hdc, HALFTONE);
// resize color channels
SelectObject(hdc, color_bitmap);
SelectObject(hdc_src, bitmap);
StretchBlt(hdc, 0, 0, width, height, hdc_src, 0, 0, bm.bmWidth,
bm.bmHeight, SRCCOPY);
// resize alpha channel
SelectObject(hdc, alpha_bitmap);
SelectObject(hdc_src, alpha_src_bitmap);
StretchBlt(hdc, 0, 0, width, height, hdc_src, 0, 0, bm.bmWidth,
bm.bmHeight, SRCCOPY);
// flush before touching the bits
GdiFlush();
// apply the alpha channel
auto* dest = reinterpret_cast<BYTE*>(color_bits);
auto* src = reinterpret_cast<const BYTE*>(alpha_bits);
auto* end = src + (width * height * 4);
while (src != end) {
dest[3] = src[0];
dest += 4;
src += 4;
}
// create the resulting bitmap
result_bitmap =
CreateDIBitmap(hdc_screen, &bmi, CBM_INIT, color_bits,
reinterpret_cast<BITMAPINFO*>(&bmi), DIB_RGB_COLORS);
}
if (hdc_src)
DeleteDC(hdc_src);
if (hdc)
DeleteDC(hdc);
if (alpha_bitmap)
DeleteObject(alpha_bitmap);
if (color_bitmap)
DeleteObject(color_bitmap);
DeleteObject(alpha_src_bitmap);
}
ReleaseDC(NULL, hdc_screen);
return result_bitmap;
}