// Copyright 2018 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "CEF/OsrRenderHandlerWinNative.h" #include "include/base/cef_callback.h" #include "include/wrapper/cef_closure_task.h" #include "include/wrapper/cef_helpers.h" #include "CEF/UtilWin.h" OsrRenderHandlerWinNative::OsrRenderHandlerWinNative( const OsrRendererSettings& settings, HWND hwnd) : OsrRenderHandlerWin(settings, hwnd), hdc_(nullptr), hrc_(nullptr), painting_popup_(false), view_width_(0), view_height_(0), spin_x_(0), spin_y_(0) {} void OsrRenderHandlerWinNative::Initialize(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); SetBrowser(browser); } OsrRenderHandlerWinNative::~OsrRenderHandlerWinNative() { CEF_REQUIRE_UI_THREAD(); } void OsrRenderHandlerWinNative::SetSpin(float spinX, float spinY) { CEF_REQUIRE_UI_THREAD(); spin_x_ = spinX; spin_y_ = spinY; Invalidate(); } void OsrRenderHandlerWinNative::IncrementSpin(float spinDX, float spinDY) { CEF_REQUIRE_UI_THREAD(); spin_x_ -= spinDX; spin_y_ -= spinDY; Invalidate(); } bool OsrRenderHandlerWinNative::IsOverPopupWidget(int x, int y) const { CEF_REQUIRE_UI_THREAD(); const CefRect& rc = popup_rect_; int popup_right = rc.x + rc.width; int popup_bottom = rc.y + rc.height; return (x >= rc.x) && (x < popup_right) && (y >= rc.y) && (y < popup_bottom); } int OsrRenderHandlerWinNative::GetPopupXOffset() const { CEF_REQUIRE_UI_THREAD(); return original_popup_rect_.x - popup_rect_.x; } int OsrRenderHandlerWinNative::GetPopupYOffset() const { CEF_REQUIRE_UI_THREAD(); return original_popup_rect_.y - popup_rect_.y; } void OsrRenderHandlerWinNative::OnPopupShow(CefRefPtr browser, bool show) { CEF_REQUIRE_UI_THREAD(); if (!show) { popup_rect_.Set(0, 0, 0, 0); original_popup_rect_.Set(0, 0, 0, 0); browser->GetHost()->Invalidate(PET_VIEW); } } void OsrRenderHandlerWinNative::OnPopupSize(CefRefPtr browser, const CefRect& rect) { CEF_REQUIRE_UI_THREAD(); if (rect.width <= 0 || rect.height <= 0) return; original_popup_rect_ = rect; popup_rect_ = GetPopupRectInWebView(original_popup_rect_); } void OsrRenderHandlerWinNative::OnPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, const void* buffer, int width, int height) { CEF_REQUIRE_UI_THREAD() // stbi_write_png("d:/3.png", width, height, 4, buffer, width * 4); HDC hDc = GetDC(hwnd()); HDC hMemDC = CreateCompatibleDC(hDc); RECT rct; GetClientRect(hwnd(), &rct); BITMAPINFO bmi = { 0 }; bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biWidth = width; bmi.bmiHeader.biHeight = height; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; DWORD *pvBits = nullptr; HBITMAP hBitmap = CreateDIBSection(hDc, &bmi, DIB_RGB_COLORS, reinterpret_cast(&pvBits), NULL, 0); const int iTotal = width * height * 4; // for (int i = 0; i != height; ++i) // { // for (int j = 0; j != width; ++j) // { // pvBits[i * width + j] = reinterpret_cast(buffer)[(height - i - 1) * width + j]; // byte *pByte = (byte*)&pvBits[i * width + j]; // pByte[0] = pByte[0] * pByte[3] / 255; // pByte[1] = pByte[1] * pByte[3] / 255; // pByte[2] = pByte[2] * pByte[3] / 255; // } // } memcpy(pvBits, buffer, iTotal); GdiFlush(); SelectObject(hMemDC, hBitmap); POINT ptSrc; ptSrc.x = 0; ptSrc.y = 0; POINT ptDst = ptSrc; // ClientToScreen(hwnd(), &ptDst); SIZE szSrc; szSrc.cx = width; szSrc.cy = height; BLENDFUNCTION bf; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; PAINTSTRUCT ps; BeginPaint(hwnd(), &ps); EndPaint(hwnd(), &ps); UpdateLayeredWindow(hwnd(), hDc, &ptDst, &szSrc, hMemDC, &ptSrc, 0, &bf, ULW_ALPHA); DeleteDC(hMemDC); DeleteObject(hBitmap); ReleaseDC(hwnd(), hDc); } void OsrRenderHandlerWinNative::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, void* share_handle) { // Not used with this implementation. NOTREACHED(); } void OsrRenderHandlerWinNative::Render() { } CefRect OsrRenderHandlerWinNative::GetPopupRectInWebView(const CefRect& original_rect) { CefRect rc(original_rect); // if x or y are negative, move them to 0. if (rc.x < 0) rc.x = 0; if (rc.y < 0) rc.y = 0; // if popup goes outside the view, try to reposition origin if (rc.x + rc.width > view_width_) rc.x = view_width_ - rc.width; if (rc.y + rc.height > view_height_) rc.y = view_height_ - rc.height; // if x or y became negative, move them to 0 again. if (rc.x < 0) rc.x = 0; if (rc.y < 0) rc.y = 0; return rc; }