Skip to content

Commit 5e16914

Browse files
authored
OffScreen - Fix ResizeAsync with deviceScalingFactor (#3964)
* OffScreen - Fix ResizeAsync with deviceScalingFactor * OffScreen - Fix CaptureScreenshotAsync Width / Height calculation to include X and Y Always apply Scale changes
1 parent 543e9d9 commit 5e16914

File tree

2 files changed

+137
-6
lines changed

2 files changed

+137
-6
lines changed

CefSharp.OffScreen/ChromiumWebBrowser.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -543,20 +543,35 @@ public async Task<byte[]> CaptureScreenshotAsync(CaptureScreenshotFormat? format
543543

544544
using (var devToolsClient = browser.GetDevToolsClient())
545545
{
546-
if(viewport == null)
546+
if (viewport == null)
547547
{
548548
var screenShot = await devToolsClient.Page.CaptureScreenshotAsync(format, quality, fromSurface: true).ConfigureAwait(continueOnCapturedContext: false);
549549

550550
return screenShot.Data;
551551
}
552552

553-
//TODO: Check scale
554553
//https://bitbucket.org/chromiumembedded/cef/issues/3103/offscreen-capture-screenshot-with-devtools
555554
//CEF OSR mode doesn't set the size internally when CaptureScreenShot is called with a clip param specified, so
556555
//we must manually resize our view if size is greater
557-
if (viewport.Scale > deviceScaleFactor || (int)viewport.Width > size.Width || (int)viewport.Height > size.Height)
556+
var newWidth = viewport.Width + viewport.X;
557+
if (newWidth < size.Width)
558558
{
559-
await ResizeAsync((int)viewport.Width, (int)viewport.Height, (float)viewport.Scale).ConfigureAwait(continueOnCapturedContext:false);
559+
newWidth = size.Width;
560+
}
561+
var newHeight = viewport.Height + viewport.Y;
562+
if (newHeight < size.Height)
563+
{
564+
newHeight = size.Height;
565+
}
566+
var newScale = viewport.Scale;
567+
if (newScale == 0)
568+
{
569+
newScale = deviceScaleFactor;
570+
}
571+
572+
if ((int)newWidth > size.Width || (int)newHeight > size.Height || newScale != deviceScaleFactor)
573+
{
574+
await ResizeAsync((int)newWidth, (int)newHeight, (float)newScale).ConfigureAwait(continueOnCapturedContext:false);
560575
}
561576

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

595-
if(size.Width == width && size.Height == height && deviceScaleFactor == null)
610+
if (size.Width == width && size.Height == height && (deviceScaleFactor == null || deviceScaleFactor == DeviceScaleFactor))
596611
{
597612
return Task.FromResult(true);
598613
}
599614

615+
var scaledWidth = (int)(width * DeviceScaleFactor);
616+
var scaledHeight = (int)(height * DeviceScaleFactor);
617+
600618
var tcs = new TaskCompletionSource<bool>();
601619
EventHandler<OnPaintEventArgs> handler = null;
602620

603621
handler = (s, e) =>
604622
{
605-
if (e.Width == width && e.Height == height)
623+
if (e.Width == scaledWidth && e.Height == scaledHeight)
606624
{
607625
AfterPaint -= handler;
608626

@@ -616,6 +634,8 @@ public Task ResizeAsync(int width, int height, float? deviceScaleFactor = null)
616634
//a call to NotifyScreenInfoChanged will be made.
617635
if (deviceScaleFactor.HasValue)
618636
{
637+
scaledWidth = (int)(width * deviceScaleFactor.Value);
638+
scaledHeight = (int)(height * deviceScaleFactor.Value);
619639
DeviceScaleFactor = deviceScaleFactor.Value;
620640
}
621641
Size = new Size(width, height);

CefSharp.Test/OffScreen/OffScreenBrowserBasicFacts.cs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
using System;
66
using System.Collections.Generic;
7+
using System.Drawing;
8+
using System.IO;
79
using System.Linq;
810
using System.Net;
911
using System.Text;
1012
using System.Threading;
1113
using System.Threading.Tasks;
14+
using CefSharp.DevTools.Page;
1215
using CefSharp.Example;
1316
using CefSharp.Example.Handlers;
1417
using CefSharp.Internals;
@@ -774,6 +777,114 @@ public async Task CanCallTryGetBrowserCoreByIdWithOwnId()
774777
}
775778
}
776779

780+
[Fact]
781+
public async Task CanCaptureScreenshotAsync()
782+
{
783+
using (var browser = new ChromiumWebBrowser("http://www.google.com"))
784+
{
785+
var response = await browser.WaitForInitialLoadAsync();
786+
787+
Assert.True(response.Success);
788+
789+
var result1 = await browser.CaptureScreenshotAsync();
790+
Assert.Equal(1366, browser.Size.Width);
791+
Assert.Equal(768, browser.Size.Height);
792+
Assert.Equal(1, browser.DeviceScaleFactor);
793+
using (var screenshot = Image.FromStream(new MemoryStream(result1)))
794+
{
795+
Assert.Equal(1366, screenshot.Width);
796+
Assert.Equal(768, screenshot.Height);
797+
}
798+
799+
800+
var result2 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 1366, Height = 768, X = 100, Y = 200, Scale = 2 });
801+
Assert.Equal(1466, browser.Size.Width);
802+
Assert.Equal(968, browser.Size.Height);
803+
Assert.Equal(2, browser.DeviceScaleFactor);
804+
using (var screenshot = Image.FromStream(new MemoryStream(result2)))
805+
{
806+
Assert.Equal(2732, screenshot.Width);
807+
Assert.Equal(1536, screenshot.Height);
808+
}
809+
810+
811+
var result3 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 100, Height = 200 });
812+
Assert.Equal(1466, browser.Size.Width);
813+
Assert.Equal(968, browser.Size.Height);
814+
Assert.Equal(2, browser.DeviceScaleFactor);
815+
using (var screenshot = Image.FromStream(new MemoryStream(result3)))
816+
{
817+
Assert.Equal(200, screenshot.Width);
818+
Assert.Equal(400, screenshot.Height);
819+
}
820+
821+
822+
var result4 = await browser.CaptureScreenshotAsync(viewport: new Viewport { Width = 100, Height = 200, Scale = 1 });
823+
Assert.Equal(1466, browser.Size.Width);
824+
Assert.Equal(968, browser.Size.Height);
825+
Assert.Equal(1, browser.DeviceScaleFactor);
826+
using (var screenshot = Image.FromStream(new MemoryStream(result4)))
827+
{
828+
Assert.Equal(100, screenshot.Width);
829+
Assert.Equal(200, screenshot.Height);
830+
}
831+
}
832+
}
833+
834+
[Fact]
835+
public async Task CanResizeWithDeviceScalingFactor()
836+
{
837+
using (var browser = new ChromiumWebBrowser("http://www.google.com"))
838+
{
839+
var response = await browser.WaitForInitialLoadAsync();
840+
841+
Assert.True(response.Success);
842+
843+
Assert.Equal(1366, browser.Size.Width);
844+
Assert.Equal(768, browser.Size.Height);
845+
Assert.Equal(1, browser.DeviceScaleFactor);
846+
847+
848+
await browser.ResizeAsync(800, 600, 2);
849+
850+
Assert.Equal(800, browser.Size.Width);
851+
Assert.Equal(600, browser.Size.Height);
852+
Assert.Equal(2, browser.DeviceScaleFactor);
853+
854+
using (var screenshot = browser.ScreenshotOrNull())
855+
{
856+
Assert.Equal(1600, screenshot.Width);
857+
Assert.Equal(1200, screenshot.Height);
858+
}
859+
860+
861+
await browser.ResizeAsync(400, 300);
862+
863+
Assert.Equal(400, browser.Size.Width);
864+
Assert.Equal(300, browser.Size.Height);
865+
Assert.Equal(2, browser.DeviceScaleFactor);
866+
867+
using (var screenshot = browser.ScreenshotOrNull())
868+
{
869+
Assert.Equal(800, screenshot.Width);
870+
Assert.Equal(600, screenshot.Height);
871+
}
872+
873+
874+
await browser.ResizeAsync(1366, 768, 1);
875+
876+
Assert.Equal(1366, browser.Size.Width);
877+
Assert.Equal(768, browser.Size.Height);
878+
Assert.Equal(1, browser.DeviceScaleFactor);
879+
880+
using (var screenshot = browser.ScreenshotOrNull())
881+
{
882+
Assert.Equal(1366, screenshot.Width);
883+
Assert.Equal(768, screenshot.Height);
884+
}
885+
}
886+
}
887+
777888
#if DEBUG
778889
[Fact]
779890
public async Task CanLoadMultipleBrowserInstancesSequentially()

0 commit comments

Comments
 (0)