Recently there was a thread on the matplotlib-users mailing list about the speed of the PDF backend:
http://sourceforge.net/mailarchive/forum.php?thread_name=4FF926B8.1030202%40hawaii.edu&forum_name=matplotlib-users
Whereas the Mac OS X and the Cairo backends make use of new_gc and gc.restore to keep track of the graphics context, the PDF backend uses check_gc and an internal stack of graphics contexts. Since nowadays matplotlib has gc.restore functionality, I don't think that that is needed any more. Removing these bits of code from the PDF backend may speed up this backend, as well as result in smaller PDF files.
See this revision for when gc.restore was added to matplotlib:
http://matplotlib.svn.sourceforge.net/viewvc/matplotlib?view=revision&revision=7112
The principles behind graphics with Mac OS X and Cairo are very similar to those of PDF, so one could simply look at those backends and use the corresponding code in the PDF backend.
Probably the Cairo backend is easiest to follow, as it is in pure Python.
Below is an outline of what is needed. The key point is that since nowadays each call to new_gc is balanced by a call to gc.restore, we can simply print out Op.gsave and Op.grestore directly without having to push and pop GraphicsContextPdf instances. The other operations on the GraphicsContextPdf object can also be executed directly.
In the RendererPDF class:
In the init method,
self.gc = self.new_gc()
should be replaced with
self.gc = GraphicsContextPdf(self.file)
The check_gc method and all calls to this method can be removed.
In the draw_image method, we need to still do the clipping, and we need to add something like
clippath, clippath_trans = gc.get_clip_path()
and output Op.clip appropriately somewhere between the Op.gsave and Op.grestore. (It may help to look at the Cairo backend to see how this method is implemented there).
In the draw_path method, if rgbFace is not None, then between an Op.gsave and an Op.grestore we need to change the fill color by Op.setrgb_nonstroke. (Comparing to the Cairo backend may help here).
In the new_gc method, instead of creating a new GraphicsContextPdf object, we simply apply Op.gsave to the current graphics context object. This is the important part.
In the GraphicsContextPdf class:
We need to add a method "restore" which emits Op.grestore. Since in matplotlib each call to new_gc is balanced with a call to restore, each Op.gsave is balanced by an Op.grestore.
The following methods should be renamed, and the corresponding PDF operation can now be executed directly:
capstyle_cmd ---> set_capstyle
joinstyle_cmd ---> set_joinstyle
linewidth_cmd ---> set_linewidth
dash_cmd ---> set_dashes
alpha_cmd ---> set_alpha
rgb_cmd ---> set_foreground
For the method hatch_cmd, I am not quite sure how to implement it for PDF. Hatching was not implemented for the Cairo background, but it was implemented for the MacOSX backend (in the C code), so it must be possible in the PDF backend also.
The push and pop methods can be removed.
Instead of the method clip_cmd, we new need a method set_clip_path. This method can apply Op.clip directly, without having to search for the appropriate graphics context.
The delta method and the copy_properties methods can be removed.
The repr method can be removed.
The .parent attribute can be removed.
Recently there was a thread on the matplotlib-users mailing list about the speed of the PDF backend:
http://sourceforge.net/mailarchive/forum.php?thread_name=4FF926B8.1030202%40hawaii.edu&forum_name=matplotlib-users
Whereas the Mac OS X and the Cairo backends make use of new_gc and gc.restore to keep track of the graphics context, the PDF backend uses check_gc and an internal stack of graphics contexts. Since nowadays matplotlib has gc.restore functionality, I don't think that that is needed any more. Removing these bits of code from the PDF backend may speed up this backend, as well as result in smaller PDF files.
See this revision for when gc.restore was added to matplotlib:
http://matplotlib.svn.sourceforge.net/viewvc/matplotlib?view=revision&revision=7112
The principles behind graphics with Mac OS X and Cairo are very similar to those of PDF, so one could simply look at those backends and use the corresponding code in the PDF backend.
Probably the Cairo backend is easiest to follow, as it is in pure Python.
Below is an outline of what is needed. The key point is that since nowadays each call to new_gc is balanced by a call to gc.restore, we can simply print out Op.gsave and Op.grestore directly without having to push and pop GraphicsContextPdf instances. The other operations on the GraphicsContextPdf object can also be executed directly.
In the RendererPDF class:
In the init method,
self.gc = self.new_gc()
should be replaced with
self.gc = GraphicsContextPdf(self.file)
The check_gc method and all calls to this method can be removed.
In the draw_image method, we need to still do the clipping, and we need to add something like
clippath, clippath_trans = gc.get_clip_path()
and output Op.clip appropriately somewhere between the Op.gsave and Op.grestore. (It may help to look at the Cairo backend to see how this method is implemented there).
In the draw_path method, if rgbFace is not None, then between an Op.gsave and an Op.grestore we need to change the fill color by Op.setrgb_nonstroke. (Comparing to the Cairo backend may help here).
In the new_gc method, instead of creating a new GraphicsContextPdf object, we simply apply Op.gsave to the current graphics context object. This is the important part.
In the GraphicsContextPdf class:
We need to add a method "restore" which emits Op.grestore. Since in matplotlib each call to new_gc is balanced with a call to restore, each Op.gsave is balanced by an Op.grestore.
The following methods should be renamed, and the corresponding PDF operation can now be executed directly:
capstyle_cmd ---> set_capstyle
joinstyle_cmd ---> set_joinstyle
linewidth_cmd ---> set_linewidth
dash_cmd ---> set_dashes
alpha_cmd ---> set_alpha
rgb_cmd ---> set_foreground
For the method hatch_cmd, I am not quite sure how to implement it for PDF. Hatching was not implemented for the Cairo background, but it was implemented for the MacOSX backend (in the C code), so it must be possible in the PDF backend also.
The push and pop methods can be removed.
Instead of the method clip_cmd, we new need a method set_clip_path. This method can apply Op.clip directly, without having to search for the appropriate graphics context.
The delta method and the copy_properties methods can be removed.
The repr method can be removed.
The .parent attribute can be removed.