HumanRender/human_render/CEF/OsrRenderHandlerWinNative.cpp

182 lines
5.2 KiB
C++
Raw Normal View History

2024-12-19 17:46:41 +00:00
// 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<CefBrowser> 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<void**>(&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<const DWORD*>(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<CefBrowser> 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;
}