in shell/browser/notifications/win/win32_desktop_notifications/toast.cc [519:637]
void DesktopNotificationController::Toast::UpdateBufferSize() {
if (hdc_) {
SIZE new_size;
{
TEXTMETRIC tm_cap = {};
HFONT font = data_->controller->GetCaptionFont();
if (font) {
SelectFont(hdc_, font);
if (!GetTextMetrics(hdc_, &tm_cap))
return;
}
TEXTMETRIC tm_body = {};
font = data_->controller->GetBodyFont();
if (font) {
SelectFont(hdc_, font);
if (!GetTextMetrics(hdc_, &tm_body))
return;
}
this->margin_ = {tm_cap.tmAveCharWidth * 2, tm_cap.tmAscent / 2};
new_size.cx = margin_.cx + (32 * tm_cap.tmAveCharWidth) + margin_.cx;
new_size.cy = margin_.cy + (tm_cap.tmHeight) + margin_.cy;
if (!data_->body_text.empty())
new_size.cy += margin_.cy + (3 * tm_body.tmHeight);
if (data_->image) {
BITMAP bm;
if (GetObject(data_->image, sizeof(bm), &bm)) {
// cap the image size
const int max_dim_size = 80;
auto width = bm.bmWidth;
auto height = bm.bmHeight;
if (width < height) {
if (height > max_dim_size) {
width = width * max_dim_size / height;
height = max_dim_size;
}
} else {
if (width > max_dim_size) {
height = height * max_dim_size / width;
width = max_dim_size;
}
}
ScreenMetrics scr;
SIZE image_draw_size = {scr.X(width), scr.Y(height)};
new_size.cx += image_draw_size.cx + margin_.cx;
auto height_with_image =
margin_.cy + (image_draw_size.cy) + margin_.cy;
if (new_size.cy < height_with_image)
new_size.cy = height_with_image;
UpdateScaledImage(image_draw_size);
}
}
}
if (new_size.cx != this->toast_size_.cx ||
new_size.cy != this->toast_size_.cy) {
HDC hdc_screen = GetDC(NULL);
auto* new_bitmap =
CreateCompatibleBitmap(hdc_screen, new_size.cx, new_size.cy);
ReleaseDC(NULL, hdc_screen);
if (new_bitmap) {
if (SelectBitmap(hdc_, new_bitmap)) {
RECT dirty1 = {}, dirty2 = {};
if (toast_size_.cx < new_size.cx) {
dirty1 = {toast_size_.cx, 0, new_size.cx, toast_size_.cy};
}
if (toast_size_.cy < new_size.cy) {
dirty2 = {0, toast_size_.cy, new_size.cx, new_size.cy};
}
if (this->bitmap_)
DeleteBitmap(this->bitmap_);
this->bitmap_ = new_bitmap;
this->toast_size_ = new_size;
Invalidate();
// Resize also the DWM buffer to prevent flicker during
// window resizing. Make sure any existing data is not
// overwritten by marking the dirty region.
{
POINT origin = {0, 0};
UPDATELAYEREDWINDOWINFO ulw;
ulw.cbSize = sizeof(ulw);
ulw.hdcDst = NULL;
ulw.pptDst = nullptr;
ulw.psize = &toast_size_;
ulw.hdcSrc = hdc_;
ulw.pptSrc = &origin;
ulw.crKey = 0;
ulw.pblend = nullptr;
ulw.dwFlags = 0;
ulw.prcDirty = &dirty1;
auto b1 = UpdateLayeredWindowIndirect(hwnd_, &ulw);
ulw.prcDirty = &dirty2;
auto b2 = UpdateLayeredWindowIndirect(hwnd_, &ulw);
DCHECK(b1 && b2);
}
return;
}
DeleteBitmap(new_bitmap);
}
}
}
}