Skip to content

Commit

Permalink
OffScreen - Fix ResizeAsync with deviceScalingFactor (cefsharp#3964)
Browse files Browse the repository at this point in the history
* OffScreen - Fix ResizeAsync with deviceScalingFactor

* OffScreen - Fix CaptureScreenshotAsync Width / Height calculation to include X and Y

Always apply Scale changes
  • Loading branch information
campersau authored Jan 18, 2022
1 parent 543e9d9 commit 5e16914
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 6 deletions.
32 changes: 26 additions & 6 deletions CefSharp.OffScreen/ChromiumWebBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -543,20 +543,35 @@ public async Task<byte[]> CaptureScreenshotAsync(CaptureScreenshotFormat? format

using (var devToolsClient = browser.GetDevToolsClient())
{
if(viewport == null)
if (viewport == null)
{
var screenShot = await devToolsClient.Page.CaptureScreenshotAsync(format, quality, fromSurface: true).ConfigureAwait(continueOnCapturedContext: false);

return screenShot.Data;
}

//TODO: Check scale
//https://bitbucket.org/chromiumembedded/cef/issues/3103/offscreen-capture-screenshot-with-devtools
//CEF OSR mode doesn't set the size internally when CaptureScreenShot is called with a clip param specified, so
//we must manually resize our view if size is greater
if (viewport.Scale > deviceScaleFactor || (int)viewport.Width > size.Width || (int)viewport.Height > size.Height)
var newWidth = viewport.Width + viewport.X;
if (newWidth < size.Width)
{
await ResizeAsync((int)viewport.Width, (int)viewport.Height, (float)viewport.Scale).ConfigureAwait(continueOnCapturedContext:false);
newWidth = size.Width;
}
var newHeight = viewport.Height + viewport.Y;
if (newHeight < size.Height)
{
newHeight = size.Height;
}
var newScale = viewport.Scale;
if (newScale == 0)
{
newScale = deviceScaleFactor;
}

if ((int)newWidth > size.Width || (int)newHeight > size.Height || newScale != deviceScaleFactor)
{
await ResizeAsync((int)newWidth, (int)newHeight, (float)newScale).ConfigureAwait(continueOnCapturedContext:false);
}

//Create a copy instead of modifying users object as we need to set Scale to 1
Expand Down Expand Up @@ -592,17 +607,20 @@ public Task ResizeAsync(int width, int height, float? deviceScaleFactor = null)
ThrowExceptionIfDisposed();
ThrowExceptionIfBrowserNotInitialized();

if(size.Width == width && size.Height == height && deviceScaleFactor == null)
if (size.Width == width && size.Height == height && (deviceScaleFactor == null || deviceScaleFactor == DeviceScaleFactor))
{
return Task.FromResult(true);
}

var scaledWidth = (int)(width * DeviceScaleFactor);
var scaledHeight = (int)(height * DeviceScaleFactor);

var tcs = new TaskCompletionSource<bool>();
EventHandler<OnPaintEventArgs> handler = null;

handler = (s, e) =>
{
if (e.Width == width && e.Height == height)
if (e.Width == scaledWidth && e.Height == scaledHeight)
{
AfterPaint -= handler;

Expand All @@ -616,6 +634,8 @@ public Task ResizeAsync(int width, int height, float? deviceScaleFactor = null)
//a call to NotifyScreenInfoChanged will be made.
if (deviceScaleFactor.HasValue)
{
scaledWidth = (int)(width * deviceScaleFactor.Value);
scaledHeight = (int)(height * deviceScaleFactor.Value);
DeviceScaleFactor = deviceScaleFactor.Value;
}
Size = new Size(width, height);
Expand Down
111 changes: 111 additions & 0 deletions CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CefSharp.DevTools.Page;
using CefSharp.Example;
using CefSharp.Example.Handlers;
using CefSharp.Internals;
Expand Down Expand Up @@ -774,6 +777,114 @@ public async Task CanCallTryGetBrowserCoreByIdWithOwnId()
}
}

[Fact]
public async Task CanCaptureScreenshotAsync()
{
using (var browser = new ChromiumWebBrowser("http://www.google.com"))
{
var response = await browser.WaitForInitialLoadAsync();

Assert.True(response.Success);

var result1 = await browser.CaptureScreenshotAsync();
Assert.Equal(1366, browser.Size.Width);
Assert.Equal(768, browser.Size.Height);
Assert.Equal(1, browser.DeviceScaleFactor);
using (var screenshot = Image.FromStream(new MemoryStream(result1)))
{
Assert.Equal(1366, screenshot.Width);
Assert.Equal(768, screenshot.Height);
}


var result2 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 1366, Height = 768, X = 100, Y = 200, Scale = 2 });
Assert.Equal(1466, browser.Size.Width);
Assert.Equal(968, browser.Size.Height);
Assert.Equal(2, browser.DeviceScaleFactor);
using (var screenshot = Image.FromStream(new MemoryStream(result2)))
{
Assert.Equal(2732, screenshot.Width);
Assert.Equal(1536, screenshot.Height);
}


var result3 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 100, Height = 200 });
Assert.Equal(1466, browser.Size.Width);
Assert.Equal(968, browser.Size.Height);
Assert.Equal(2, browser.DeviceScaleFactor);
using (var screenshot = Image.FromStream(new MemoryStream(result3)))
{
Assert.Equal(200, screenshot.Width);
Assert.Equal(400, screenshot.Height);
}


var result4 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 100, Height = 200, Scale = 1 });
Assert.Equal(1466, browser.Size.Width);
Assert.Equal(968, browser.Size.Height);
Assert.Equal(1, browser.DeviceScaleFactor);
using (var screenshot = Image.FromStream(new MemoryStream(result4)))
{
Assert.Equal(100, screenshot.Width);
Assert.Equal(200, screenshot.Height);
}
}
}

[Fact]
public async Task CanResizeWithDeviceScalingFactor()
{
using (var browser = new ChromiumWebBrowser("http://www.google.com"))
{
var response = await browser.WaitForInitialLoadAsync();

Assert.True(response.Success);

Assert.Equal(1366, browser.Size.Width);
Assert.Equal(768, browser.Size.Height);
Assert.Equal(1, browser.DeviceScaleFactor);


await browser.ResizeAsync(800, 600, 2);

Assert.Equal(800, browser.Size.Width);
Assert.Equal(600, browser.Size.Height);
Assert.Equal(2, browser.DeviceScaleFactor);

using (var screenshot = browser.ScreenshotOrNull())
{
Assert.Equal(1600, screenshot.Width);
Assert.Equal(1200, screenshot.Height);
}


await browser.ResizeAsync(400, 300);

Assert.Equal(400, browser.Size.Width);
Assert.Equal(300, browser.Size.Height);
Assert.Equal(2, browser.DeviceScaleFactor);

using (var screenshot = browser.ScreenshotOrNull())
{
Assert.Equal(800, screenshot.Width);
Assert.Equal(600, screenshot.Height);
}


await browser.ResizeAsync(1366, 768, 1);

Assert.Equal(1366, browser.Size.Width);
Assert.Equal(768, browser.Size.Height);
Assert.Equal(1, browser.DeviceScaleFactor);

using (var screenshot = browser.ScreenshotOrNull())
{
Assert.Equal(1366, screenshot.Width);
Assert.Equal(768, screenshot.Height);
}
}
}

#if DEBUG
[Fact]
public async Task CanLoadMultipleBrowserInstancesSequentially()
Expand Down

0 comments on commit 5e16914

Please sign in to comment.