diff --git a/lib/web_ui/lib/src/engine/compositor/canvaskit_api.dart b/lib/web_ui/lib/src/engine/compositor/canvaskit_api.dart index 211bcb4ab8e52..b799ef5ae499a 100644 --- a/lib/web_ui/lib/src/engine/compositor/canvaskit_api.dart +++ b/lib/web_ui/lib/src/engine/compositor/canvaskit_api.dart @@ -76,8 +76,8 @@ class CanvasKit { external SkGrContext MakeGrContext(int glContext); external SkSurface MakeOnScreenGLSurface( SkGrContext grContext, - double width, - double height, + int width, + int height, SkColorSpace colorSpace, ); external SkSurface MakeSWCanvasSurface(html.CanvasElement canvas); diff --git a/lib/web_ui/lib/src/engine/compositor/embedded_views.dart b/lib/web_ui/lib/src/engine/compositor/embedded_views.dart index 0a29ef7ef0495..5f8c4a9b8e73c 100644 --- a/lib/web_ui/lib/src/engine/compositor/embedded_views.dart +++ b/lib/web_ui/lib/src/engine/compositor/embedded_views.dart @@ -49,7 +49,7 @@ class HtmlViewEmbedder { Map _clipCount = {}; /// The size of the frame, in physical pixels. - ui.Size _frameSize = _computeFrameSize(); + ui.Size _frameSize = ui.window.physicalSize; void set frameSize(ui.Size size) { if (_frameSize == size) { diff --git a/lib/web_ui/lib/src/engine/compositor/layer_tree.dart b/lib/web_ui/lib/src/engine/compositor/layer_tree.dart index afde94d1c26ed..3b40be4728b39 100644 --- a/lib/web_ui/lib/src/engine/compositor/layer_tree.dart +++ b/lib/web_ui/lib/src/engine/compositor/layer_tree.dart @@ -11,7 +11,7 @@ class LayerTree { Layer? rootLayer; /// The size (in physical pixels) of the frame to paint this layer tree into. - final ui.Size frameSize = _computeFrameSize(); + final ui.Size frameSize = ui.window.physicalSize; /// The devicePixelRatio of the frame to paint this layer tree into. double? devicePixelRatio; @@ -54,14 +54,6 @@ class LayerTree { } } -ui.Size _computeFrameSize() { - final ui.Size physicalSize = ui.window.physicalSize; - return ui.Size( - physicalSize.width.truncate().toDouble(), - physicalSize.height.truncate().toDouble(), - ); -} - /// A single frame to be rendered. class Frame { /// The canvas to render this frame to. diff --git a/lib/web_ui/lib/src/engine/compositor/surface.dart b/lib/web_ui/lib/src/engine/compositor/surface.dart index e21e4b53ed293..17aac05770ecd 100644 --- a/lib/web_ui/lib/src/engine/compositor/surface.dart +++ b/lib/web_ui/lib/src/engine/compositor/surface.dart @@ -89,22 +89,20 @@ class Surface { _addedToScene = true; } + ui.Size? _currentSize; + void _createOrUpdateSurfaces(ui.Size size) { if (size.isEmpty) { throw CanvasKitError('Cannot create surfaces of empty size.'); } - final CkSurface? currentSurface = _surface; - if (currentSurface != null) { - final bool isSameSize = size.width == currentSurface.width() && - size.height == currentSurface.height(); - if (isSameSize) { - // The existing surface is still reusable. - return; - } + if (size == _currentSize) { + // The existing surface is still reusable. + return; } - currentSurface?.dispose(); + _currentSize = size; + _surface?.dispose(); _surface = null; htmlElement?.remove(); htmlElement = null; @@ -113,14 +111,28 @@ class Surface { _surface = _wrapHtmlCanvas(size); } - CkSurface _wrapHtmlCanvas(ui.Size size) { - final ui.Size logicalSize = size / ui.window.devicePixelRatio; + CkSurface _wrapHtmlCanvas(ui.Size physicalSize) { + // If `physicalSize` is not precise, use a slightly bigger canvas. This way + // we ensure that the rendred picture covers the entire browser window. + final int pixelWidth = physicalSize.width.ceil(); + final int pixelHeight = physicalSize.height.ceil(); final html.CanvasElement htmlCanvas = html.CanvasElement( - width: size.width.ceil(), height: size.height.ceil()); + width: pixelWidth, + height: pixelHeight, + ); + + // The logical size of the canvas is not based on the size of the window + // but on the size of the canvas, which, due to `ceil()` above, may not be + // the same as the window. We do not round/floor/ceil the logical size as + // CSS pixels can contain more than one physical pixel and therefore to + // match the size of the window precisely we use the most precise floating + // point value we can get. + final double logicalWidth = pixelWidth / ui.window.devicePixelRatio; + final double logicalHeight = pixelHeight / ui.window.devicePixelRatio; htmlCanvas.style ..position = 'absolute' - ..width = '${logicalSize.width.ceil()}px' - ..height = '${logicalSize.height.ceil()}px'; + ..width = '${logicalWidth}px' + ..height = '${logicalHeight}px'; htmlElement = htmlCanvas; if (webGLVersion == -1 || canvasKitForceCpuOnly) { @@ -153,8 +165,8 @@ class Surface { SkSurface? skSurface = canvasKit.MakeOnScreenGLSurface( _grContext!, - size.width, - size.height, + pixelWidth, + pixelHeight, SkColorSpaceSRGB, );