code: public MapBounds getRotatedBounds(final Rectangle2D.Double paintAreaPrecise, final Rectangle paintArea) {
          final MapBounds rotatedBounds = this.getRotatedBounds();
  
          if (rotatedBounds instanceof CenterScaleMapBounds) {
              return rotatedBounds;
          }
  
          final ReferencedEnvelope envelope = ((BBoxMapBounds) rotatedBounds).toReferencedEnvelope(null);
          // the paint area size and the map bounds are rotated independently. because
          // the paint area size is rounded to integers, the map bounds have to be adjusted
          // to these rounding changes.
          final double widthRatio = paintArea.getWidth() / paintAreaPrecise.getWidth();
          final double heightRatio = paintArea.getHeight() / paintAreaPrecise.getHeight();
  
          final double adaptedWidth = envelope.getWidth() * widthRatio;
          final double adaptedHeight = envelope.getHeight() * heightRatio;
  
          final double widthDiff = adaptedWidth - envelope.getWidth();
          final double heigthDiff = adaptedHeight - envelope.getHeight();
          envelope.expandBy(widthDiff / 2.0, heigthDiff / 2.0);
  
          return new BBoxMapBounds(envelope);
      }
docs: Return the map bounds rotated with the set rotation. The bounds are adapted to rounding changes of the
  size of the paint area.
  
  @param paintAreaPrecise The exact size of the paint area.
  @param paintArea The rounded size of the paint area.
  @return Rotated bounds.