docs: function(graph, scale, cells, x0, y0)
  	{
  		x0 = (x0 != null) ? x0 : 0;
  		y0 = (y0 != null) ? y0 : 0;
  		scale = (scale != null) ? scale : 1;
  
  		if (cells == null)
  		{
  			var model = graph.getModel();
  			cells = [model.getRoot()];
  		}
  		
  		var view = graph.getView();
  		var result = null;
  
  		// Disables events on the view
  		var eventsEnabled = view.isEventsEnabled();
  		view.setEventsEnabled(false);
  
  		// Workaround for label bounds not taken into account for image export.
  		// Creates a temporary draw pane which is used for rendering the text.
  		// Text rendering is required for finding the bounds of the labels.
  		var drawPane = view.drawPane;
  		var overlayPane = view.overlayPane;
  
  		if (graph.dialect == mxConstants.DIALECT_SVG)
  		{
  			view.drawPane = document.createElementNS(mxConstants.NS_SVG, 'g');
  			view.canvas.appendChild(view.drawPane);
  
  			// Redirects cell overlays into temporary container
  			view.overlayPane = document.createElementNS(mxConstants.NS_SVG, 'g');
  			view.canvas.appendChild(view.overlayPane);
  		}
  		else
  		{
  			view.drawPane = view.drawPane.cloneNode(false);
  			view.canvas.appendChild(view.drawPane);
  			
  			// Redirects cell overlays into temporary container
  			view.overlayPane = view.overlayPane.cloneNode(false);
  			view.canvas.appendChild(view.overlayPane);
  		}
  
  		// Resets the translation
  		var translate = view.getTranslate();
  		view.translate = new mxPoint(x0, y0);
  
  		// Creates the temporary cell states in the view
  		var temp = new mxTemporaryCellStates(graph.getView(), scale, cells);
  
  		try
  		{
  			var enc = new mxCodec();
  			result = enc.encode(graph.getView());
  		}
  		finally
  		{
  			temp.destroy();
  			view.translate = translate;
  			view.canvas.removeChild(view.drawPane);
  			view.canvas.removeChild(view.overlayPane);
  			view.drawPane = drawPane;
  			view.overlayPane = overlayPane;
  			view.setEventsEnabled(eventsEnabled);
  		}
  
  		return result;
  	}