docs: public TilePreparationInfo call() {
          return this.context.mdcContext(() -> {
              try {
                  final ReferencedEnvelope mapGeoBounds = this.bounds.toReferencedEnvelope(this.paintArea);
                  final CoordinateReferenceSystem mapProjection = mapGeoBounds.getCoordinateReferenceSystem();
                  Dimension tileSizeOnScreen = this.tiledLayer.getTileSize();
  
                  final double resolution = this.tiledLayer.getResolution();
                  Coordinate tileSizeInWorld = new Coordinate(tileSizeOnScreen.width * resolution,
                                                              tileSizeOnScreen.height * resolution);
  
                  // The minX minY of the first (minY, minY) tile
                  Coordinate gridCoverageOrigin =
                          this.tiledLayer.getMinGeoCoordinate(mapGeoBounds, tileSizeInWorld);
  
                  final String commonUrl = this.tiledLayer.createCommonUrl();
  
                  ReferencedEnvelope tileCacheBounds = this.tiledLayer.getTileCacheBounds();
                  double rowFactor = 1 / (resolution * tileSizeOnScreen.height);
                  double columnFactor = 1 / (resolution * tileSizeOnScreen.width);
  
                  int imageWidth = 0;
                  int imageHeight = 0;
                  int xIndex;
                  int yIndex = (int) Math.floor((mapGeoBounds.getMaxY() - gridCoverageOrigin.y) /
                                                        tileSizeInWorld.y) + 1;
  
                  double gridCoverageMaxX = gridCoverageOrigin.x;
                  double gridCoverageMaxY = gridCoverageOrigin.y;
  
                  List<SingleTilePreparationInfo> tiles = new ArrayList<>();
  
                  for (double geoY = gridCoverageOrigin.y; geoY < mapGeoBounds.getMaxY();
                       geoY += tileSizeInWorld.y) {
                      yIndex--;
                      imageHeight += tileSizeOnScreen.height;
                      imageWidth = 0;
                      xIndex = -1;
  
                      gridCoverageMaxY = geoY + tileSizeInWorld.y;
                      for (double geoX = gridCoverageOrigin.x; geoX < mapGeoBounds.getMaxX();
                           geoX += tileSizeInWorld.x) {
                          xIndex++;
                          imageWidth += tileSizeOnScreen.width;
                          gridCoverageMaxX = geoX + tileSizeInWorld.x;
  
                          ReferencedEnvelope tileBounds = new ReferencedEnvelope(
                                  geoX, gridCoverageMaxX, geoY, gridCoverageMaxY, mapProjection);
  
                          int row = (int) Math.round((tileCacheBounds.getMaxY() -
                                  tileBounds.getMaxY()) * rowFactor);
                          int column = (int) Math.round((tileBounds.getMinX() -
                                  tileCacheBounds.getMinX()) * columnFactor);
  
                          ClientHttpRequest tileRequest =
                                  this.tiledLayer.getTileRequest(this.httpRequestFactory,
                                                                 commonUrl, tileBounds,
                                                                 tileSizeOnScreen, column,
                                                                 row);
                          if (isInTileCacheBounds(tileCacheBounds, tileBounds)) {
                              if (isTileVisible(tileBounds)) {
                                  tileRequest = this.requestCache.register(tileRequest);
                                  tiles.add(new SingleTilePreparationInfo(xIndex, yIndex, tileRequest));
                              }
                          } else {
                              LOGGER.debug("Tile out of bounds: {}", tileRequest);
                              tiles.add(new SingleTilePreparationInfo(xIndex, yIndex, null));
                          }
                      }
                  }
  
                  return new TilePreparationInfo(tiles, imageWidth, imageHeight, gridCoverageOrigin,
                                                 gridCoverageMaxX, gridCoverageMaxY, mapProjection);
              } catch (Exception e) {
                  throw ExceptionUtils.getRuntimeException(e);
              }
          });
      }