@@ -1285,27 +1285,71 @@ static WritableImage doSnapshot(Scene scene,
12851285 Node root , BaseTransform transform , boolean depthBuffer ,
12861286 Paint fill , Camera camera , WritableImage wimg ) {
12871287
1288- Toolkit tk = Toolkit .getToolkit ();
1289- Toolkit .ImageRenderingContext context = new Toolkit .ImageRenderingContext ();
1290-
12911288 int xMin = (int )Math .floor (x );
12921289 int yMin = (int )Math .floor (y );
1293- int xMax = (int )Math .ceil (x + w );
1294- int yMax = (int )Math .ceil (y + h );
1295- int width = Math .max (xMax - xMin , 1 );
1296- int height = Math .max (yMax - yMin , 1 );
1290+ int width ;
1291+ int height ;
12971292 if (wimg == null ) {
1293+ int xMax = (int )Math .ceil (x + w );
1294+ int yMax = (int )Math .ceil (y + h );
1295+ width = Math .max (xMax - xMin , 1 );
1296+ height = Math .max (yMax - yMin , 1 );
12981297 wimg = new WritableImage (width , height );
12991298 } else {
13001299 width = (int )wimg .getWidth ();
13011300 height = (int )wimg .getHeight ();
13021301 }
13031302
1303+ // Attempt to capture snapshot
1304+ try {
1305+ wimg = doSnapshotTile (scene , xMin , yMin , width , height , root , transform , depthBuffer , fill , camera , wimg );
1306+ } catch (Exception e ) {
1307+ // A first attempt to capture a snapshot failed, most likely because it is larger than
1308+ // maxTextureSize: retry by taking several snapshot tiles and merge them into single image
1309+ // (Addresses JDK-8088198)
1310+ int maxTextureSize = PrismSettings .maxTextureSize ;
1311+ int numVerticalTiles = (int ) Math .ceil (height / (double ) maxTextureSize );
1312+ int numHorizontalTiles = (int ) Math .ceil (width / (double ) maxTextureSize );
1313+ for (int i = 0 ; i < numHorizontalTiles ; i ++) {
1314+ int xOffset = i * maxTextureSize ;
1315+ int tileWidth = Math .min (maxTextureSize , width - xOffset );
1316+ for (int j = 0 ; j < numVerticalTiles ; j ++) {
1317+ int yOffset = j * maxTextureSize ;
1318+ int tileHeight = Math .min (maxTextureSize , height - yOffset );
1319+ WritableImage tile = doSnapshotTile (scene , xMin + xOffset , yMin + yOffset , tileWidth ,
1320+ tileHeight , root , transform , depthBuffer , fill , camera , null );
1321+ wimg .getPixelWriter ().setPixels (xOffset , yOffset , tileWidth , tileHeight , tile .getPixelReader (), 0 , 0 );
1322+ }
1323+ }
1324+ }
1325+
1326+ // if this scene belongs to some stage
1327+ // we need to mark the entire scene as dirty
1328+ // because dirty logic is buggy
1329+ if (scene != null && scene .peer != null ) {
1330+ scene .setNeedsRepaint ();
1331+ }
1332+
1333+ return wimg ;
1334+ }
1335+
1336+ /**
1337+ * Capture a single snapshot tile
1338+ */
1339+ private static WritableImage doSnapshotTile (Scene scene ,
1340+ int x , int y , int w , int h ,
1341+ Node root , BaseTransform transform , boolean depthBuffer ,
1342+ Paint fill , Camera camera , WritableImage tileImg ) {
1343+ Toolkit tk = Toolkit .getToolkit ();
1344+ Toolkit .ImageRenderingContext context = new Toolkit .ImageRenderingContext ();
1345+ if (tileImg == null ) {
1346+ tileImg = new WritableImage (w , h );
1347+ }
13041348 setAllowPGAccess (true );
1305- context .x = xMin ;
1306- context .y = yMin ;
1307- context .width = width ;
1308- context .height = height ;
1349+ context .x = x ;
1350+ context .y = y ;
1351+ context .width = w ;
1352+ context .height = h ;
13091353 context .transform = transform ;
13101354 context .depthBuffer = depthBuffer ;
13111355 context .root = root .getPeer ();
@@ -1316,8 +1360,8 @@ static WritableImage doSnapshot(Scene scene,
13161360 // temporarily adjust camera viewport to the snapshot size
13171361 cameraViewWidth = camera .getViewWidth ();
13181362 cameraViewHeight = camera .getViewHeight ();
1319- camera .setViewWidth (width );
1320- camera .setViewHeight (height );
1363+ camera .setViewWidth (w );
1364+ camera .setViewHeight (h );
13211365 NodeHelper .updatePeer (camera );
13221366 context .camera = camera .getPeer ();
13231367 } else {
@@ -1334,10 +1378,10 @@ static WritableImage doSnapshot(Scene scene,
13341378 }
13351379
13361380 Toolkit .WritableImageAccessor accessor = Toolkit .getWritableImageAccessor ();
1337- context .platformImage = accessor .getTkImageLoader (wimg );
1381+ context .platformImage = accessor .getTkImageLoader (tileImg );
13381382 setAllowPGAccess (false );
13391383 Object tkImage = tk .renderToImage (context );
1340- accessor .loadTkImage (wimg , tkImage );
1384+ accessor .loadTkImage (tileImg , tkImage );
13411385
13421386 if (camera != null ) {
13431387 setAllowPGAccess (true );
@@ -1346,15 +1390,7 @@ static WritableImage doSnapshot(Scene scene,
13461390 NodeHelper .updatePeer (camera );
13471391 setAllowPGAccess (false );
13481392 }
1349-
1350- // if this scene belongs to some stage
1351- // we need to mark the entire scene as dirty
1352- // because dirty logic is buggy
1353- if (scene != null && scene .peer != null ) {
1354- scene .setNeedsRepaint ();
1355- }
1356-
1357- return wimg ;
1393+ return tileImg ;
13581394 }
13591395
13601396 /**
0 commit comments