We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
SlippyImageArtist cannot be composited
For example, take the WMTS example and add a second layer. Then attempt to save as a PDF.

``` python
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

url = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi'
layer1 = 'VIIRS_CityLights_2012'
layer2 = 'ASTER_GDEM_Color_Index'

ax = plt.axes(projection=ccrs.PlateCarree())
ax.add_wmts(url, layer1)
ax.add_wmts(url, layer2)
ax.set_extent((-15, 25, 35, 60))

plt.title('Suomi NPP Earth at night April/October 2012')
plt.savefig('test.pdf')
plt.show()
```

which results in:

``` python
Traceback (most recent call last):
  File "wmts.py", line 33, in main
    plt.savefig('test.pdf')
  File "/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py", line 577, in savefig
    res = fig.savefig(*args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 1476, in savefig
    self.canvas.print_figure(*args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py", line 161, in print_figure
    FigureCanvasAgg.print_figure(self, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/backend_bases.py", line 2211, in print_figure
    **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_pdf.py", line 2485, in print_pdf
    self.figure.draw(renderer)
  File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/figure.py", line 1085, in draw
    func(*args)
  File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/cartopy/mpl/geoaxes.py", line 359, in draw
    inframe=inframe)
  File "/usr/lib64/python2.7/site-packages/matplotlib/artist.py", line 59, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/matplotlib/axes/_base.py", line 2081, in draw
    for z, im in zorder_images]
  File "/usr/lib64/python2.7/site-packages/matplotlib/image.py", line 580, in make_image
    raise RuntimeError('You must first set the image'
RuntimeError: You must first set the image array or the image attribute
```

I think maybe `SlippyImageArtist` should be overriding `make_image`, too.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/cartopy/mpl/slippy_image_artist.py`
Content:
```
1 # (C) British Crown Copyright 2014 - 2018, Met Office
2 #
3 # This file is part of cartopy.
4 #
5 # cartopy is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU Lesser General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # cartopy is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with cartopy.  If not, see <https://www.gnu.org/licenses/>.
17 """
18 Define the SlippyImageArtist class, which interfaces with
19 :class:`cartopy.io.RasterSource` instances at draw time, for interactive
20 dragging and zooming of raster data.
21 
22 """
23 
24 from __future__ import (absolute_import, division, print_function)
25 
26 from matplotlib.image import AxesImage
27 import matplotlib.artist
28 
29 
30 class SlippyImageArtist(AxesImage):
31 
32     """
33     A subclass of :class:`~matplotlib.image.AxesImage` which provides an
34     interface for getting a raster from the given object with interactive
35     slippy map type functionality.
36 
37     Kwargs are passed to the AxesImage constructor.
38 
39     """
40     def __init__(self, ax, raster_source, **kwargs):
41         self.raster_source = raster_source
42         super(SlippyImageArtist, self).__init__(ax, **kwargs)
43         self.set_clip_path(ax.background_patch)
44         self.cache = []
45 
46         ax.figure.canvas.mpl_connect('button_press_event', self.on_press)
47         ax.figure.canvas.mpl_connect('button_release_event', self.on_release)
48 
49         self.on_release()
50 
51     def on_press(self, event=None):
52         self.user_is_interacting = True
53 
54     def on_release(self, event=None):
55         self.user_is_interacting = False
56         self.stale = True
57 
58     @matplotlib.artist.allow_rasterization
59     def draw(self, renderer, *args, **kwargs):
60         if not self.get_visible():
61             return
62 
63         ax = self.axes
64         window_extent = ax.get_window_extent()
65         [x1, y1], [x2, y2] = ax.viewLim.get_points()
66         if not self.user_is_interacting:
67             located_images = self.raster_source.fetch_raster(
68                 ax.projection, extent=[x1, x2, y1, y2],
69                 target_resolution=(window_extent.width, window_extent.height))
70             self.cache = located_images
71 
72         for img, extent in self.cache:
73             self.set_array(img)
74             with ax.hold_limits():
75                 self.set_extent(extent)
76             super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)
77
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/cartopy/mpl/slippy_image_artist.py b/lib/cartopy/mpl/slippy_image_artist.py
--- a/lib/cartopy/mpl/slippy_image_artist.py
+++ b/lib/cartopy/mpl/slippy_image_artist.py
@@ -74,3 +74,8 @@
             with ax.hold_limits():
                 self.set_extent(extent)
             super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)
+
+    def can_composite(self):
+        # As per https://github.com/SciTools/cartopy/issues/689, disable
+        # compositing multiple raster sources.
+        return False

{"golden_diff": "diff --git a/lib/cartopy/mpl/slippy_image_artist.py b/lib/cartopy/mpl/slippy_image_artist.py\n--- a/lib/cartopy/mpl/slippy_image_artist.py\n+++ b/lib/cartopy/mpl/slippy_image_artist.py\n@@ -74,3 +74,8 @@\n             with ax.hold_limits():\n                 self.set_extent(extent)\n             super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n+\n+    def can_composite(self):\n+        # As per https://github.com/SciTools/cartopy/issues/689, disable\n+        # compositing multiple raster sources.\n+        return False\n", "issue": "SlippyImageArtist cannot be composited\nFor example, take the WMTS example and add a second layer. Then attempt to save as a PDF.\n\n``` python\nimport cartopy.crs as ccrs\nimport matplotlib.pyplot as plt\n\nurl = 'http://map1c.vis.earthdata.nasa.gov/wmts-geo/wmts.cgi'\nlayer1 = 'VIIRS_CityLights_2012'\nlayer2 = 'ASTER_GDEM_Color_Index'\n\nax = plt.axes(projection=ccrs.PlateCarree())\nax.add_wmts(url, layer1)\nax.add_wmts(url, layer2)\nax.set_extent((-15, 25, 35, 60))\n\nplt.title('Suomi NPP Earth at night April/October 2012')\nplt.savefig('test.pdf')\nplt.show()\n```\n\nwhich results in:\n\n``` python\nTraceback (most recent call last):\n  File \"wmts.py\", line 33, in main\n    plt.savefig('test.pdf')\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/pyplot.py\", line 577, in savefig\n    res = fig.savefig(*args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/figure.py\", line 1476, in savefig\n    self.canvas.print_figure(*args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_qt5agg.py\", line 161, in print_figure\n    FigureCanvasAgg.print_figure(self, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backend_bases.py\", line 2211, in print_figure\n    **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/backends/backend_pdf.py\", line 2485, in print_pdf\n    self.figure.draw(renderer)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/figure.py\", line 1085, in draw\n    func(*args)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/cartopy/mpl/geoaxes.py\", line 359, in draw\n    inframe=inframe)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/artist.py\", line 59, in draw_wrapper\n    draw(artist, renderer, *args, **kwargs)\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/axes/_base.py\", line 2081, in draw\n    for z, im in zorder_images]\n  File \"/usr/lib64/python2.7/site-packages/matplotlib/image.py\", line 580, in make_image\n    raise RuntimeError('You must first set the image'\nRuntimeError: You must first set the image array or the image attribute\n```\n\nI think maybe `SlippyImageArtist` should be overriding `make_image`, too.\n\n", "before_files": [{"content": "# (C) British Crown Copyright 2014 - 2018, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <https://www.gnu.org/licenses/>.\n\"\"\"\nDefine the SlippyImageArtist class, which interfaces with\n:class:`cartopy.io.RasterSource` instances at draw time, for interactive\ndragging and zooming of raster data.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nfrom matplotlib.image import AxesImage\nimport matplotlib.artist\n\n\nclass SlippyImageArtist(AxesImage):\n\n    \"\"\"\n    A subclass of :class:`~matplotlib.image.AxesImage` which provides an\n    interface for getting a raster from the given object with interactive\n    slippy map type functionality.\n\n    Kwargs are passed to the AxesImage constructor.\n\n    \"\"\"\n    def __init__(self, ax, raster_source, **kwargs):\n        self.raster_source = raster_source\n        super(SlippyImageArtist, self).__init__(ax, **kwargs)\n        self.set_clip_path(ax.background_patch)\n        self.cache = []\n\n        ax.figure.canvas.mpl_connect('button_press_event', self.on_press)\n        ax.figure.canvas.mpl_connect('button_release_event', self.on_release)\n\n        self.on_release()\n\n    def on_press(self, event=None):\n        self.user_is_interacting = True\n\n    def on_release(self, event=None):\n        self.user_is_interacting = False\n        self.stale = True\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        if not self.get_visible():\n            return\n\n        ax = self.axes\n        window_extent = ax.get_window_extent()\n        [x1, y1], [x2, y2] = ax.viewLim.get_points()\n        if not self.user_is_interacting:\n            located_images = self.raster_source.fetch_raster(\n                ax.projection, extent=[x1, x2, y1, y2],\n                target_resolution=(window_extent.width, window_extent.height))\n            self.cache = located_images\n\n        for img, extent in self.cache:\n            self.set_array(img)\n            with ax.hold_limits():\n                self.set_extent(extent)\n            super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n", "path": "lib/cartopy/mpl/slippy_image_artist.py"}], "after_files": [{"content": "# (C) British Crown Copyright 2014 - 2018, Met Office\n#\n# This file is part of cartopy.\n#\n# cartopy is free software: you can redistribute it and/or modify it under\n# the terms of the GNU Lesser General Public License as published by the\n# Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# cartopy is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser General Public License for more details.\n#\n# You should have received a copy of the GNU Lesser General Public License\n# along with cartopy.  If not, see <https://www.gnu.org/licenses/>.\n\"\"\"\nDefine the SlippyImageArtist class, which interfaces with\n:class:`cartopy.io.RasterSource` instances at draw time, for interactive\ndragging and zooming of raster data.\n\n\"\"\"\n\nfrom __future__ import (absolute_import, division, print_function)\n\nfrom matplotlib.image import AxesImage\nimport matplotlib.artist\n\n\nclass SlippyImageArtist(AxesImage):\n\n    \"\"\"\n    A subclass of :class:`~matplotlib.image.AxesImage` which provides an\n    interface for getting a raster from the given object with interactive\n    slippy map type functionality.\n\n    Kwargs are passed to the AxesImage constructor.\n\n    \"\"\"\n    def __init__(self, ax, raster_source, **kwargs):\n        self.raster_source = raster_source\n        super(SlippyImageArtist, self).__init__(ax, **kwargs)\n        self.set_clip_path(ax.background_patch)\n        self.cache = []\n\n        ax.figure.canvas.mpl_connect('button_press_event', self.on_press)\n        ax.figure.canvas.mpl_connect('button_release_event', self.on_release)\n\n        self.on_release()\n\n    def on_press(self, event=None):\n        self.user_is_interacting = True\n\n    def on_release(self, event=None):\n        self.user_is_interacting = False\n        self.stale = True\n\n    @matplotlib.artist.allow_rasterization\n    def draw(self, renderer, *args, **kwargs):\n        if not self.get_visible():\n            return\n\n        ax = self.axes\n        window_extent = ax.get_window_extent()\n        [x1, y1], [x2, y2] = ax.viewLim.get_points()\n        if not self.user_is_interacting:\n            located_images = self.raster_source.fetch_raster(\n                ax.projection, extent=[x1, x2, y1, y2],\n                target_resolution=(window_extent.width, window_extent.height))\n            self.cache = located_images\n\n        for img, extent in self.cache:\n            self.set_array(img)\n            with ax.hold_limits():\n                self.set_extent(extent)\n            super(SlippyImageArtist, self).draw(renderer, *args, **kwargs)\n\n    def can_composite(self):\n        # As per https://github.com/SciTools/cartopy/issues/689, disable\n        # compositing multiple raster sources.\n        return False\n", "path": "lib/cartopy/mpl/slippy_image_artist.py"}]}