@@ -20,6 +20,7 @@ typedef RenderResult = ({
2020// composite pictures into the canvases in the DOM tree it builds.
2121abstract class PictureRenderer {
2222 FutureOr <RenderResult > renderPictures (List <ScenePicture > picture);
23+ ScenePicture clipPicture (ScenePicture picture, ui.Rect clip);
2324}
2425
2526class _SceneRender {
@@ -86,20 +87,49 @@ class EngineSceneView {
8687 }
8788 }
8889
90+ ScenePicture _clipPictureIfNeeded (ScenePicture picture, ui.Rect clip) {
91+ final ui.Rect pictureRect = picture.cullRect;
92+ if (pictureRect.left >= clip.left &&
93+ pictureRect.top >= clip.top &&
94+ pictureRect.right <= clip.right &&
95+ pictureRect.bottom <= clip.bottom) {
96+ // The picture is already within the clip bounds.
97+ return picture;
98+ }
99+
100+ return pictureRenderer.clipPicture (picture, clip);
101+ }
102+
103+ ui.Rect ? _getScreenBounds () {
104+ final DomScreen ? screen = domWindow.screen;
105+ if (screen == null ) {
106+ return null ;
107+ }
108+ return ui.Rect .fromLTWH (0 , 0 , screen.width, screen.height);
109+ }
110+
89111 Future <void > _renderScene (EngineScene scene, FrameTimingRecorder ? recorder) async {
112+ final ui.Rect ? screenBounds = _getScreenBounds ();
113+ if (screenBounds == null ) {
114+ // The browser isn't displaying the document. Skip rendering.
115+ return ;
116+ }
90117 final List <LayerSlice > slices = scene.rootLayer.slices;
91118 final List <ScenePicture > picturesToRender = < ScenePicture > [];
119+ final List <ScenePicture > originalPicturesToRender = < ScenePicture > [];
92120 for (final LayerSlice slice in slices) {
93- if (slice is PictureSlice ) {
94- picturesToRender.add (slice.picture);
121+ if (slice is PictureSlice && ! slice.picture.cullRect.isEmpty) {
122+ originalPicturesToRender.add (slice.picture);
123+ final ScenePicture clippedPicture = _clipPictureIfNeeded (slice.picture, screenBounds);
124+ picturesToRender.add (clippedPicture);
95125 }
96126 }
97127 final Map <ScenePicture , DomImageBitmap > renderMap;
98128 if (picturesToRender.isNotEmpty) {
99129 final RenderResult renderResult = await pictureRenderer.renderPictures (picturesToRender);
100130 renderMap = < ScenePicture , DomImageBitmap > {
101131 for (int i = 0 ; i < picturesToRender.length; i++ )
102- picturesToRender [i]: renderResult.imageBitmaps[i],
132+ originalPicturesToRender [i]: renderResult.imageBitmaps[i],
103133 };
104134 recorder? .recordRasterStart (renderResult.rasterStartMicros);
105135 recorder? .recordRasterFinish (renderResult.rasterEndMicros);
@@ -125,10 +155,11 @@ class EngineSceneView {
125155 }
126156 }
127157
158+ final ui.Rect clippedBounds = slice.picture.cullRect.intersect (screenBounds);
128159 if (container != null ) {
129- container.bounds = slice.picture.cullRect ;
160+ container.bounds = clippedBounds ;
130161 } else {
131- container = PictureSliceContainer (slice.picture.cullRect );
162+ container = PictureSliceContainer (clippedBounds );
132163 }
133164 container.updateContents ();
134165 container.renderBitmap (renderMap[slice.picture]! );
0 commit comments