2929def _fn_name (): return sys ._getframe (1 ).f_code .co_name
3030
3131from matplotlib import verbose
32- from matplotlib .numerix import asarray , pi , fromstring , UInt8 #, zeros, where,
33- #transpose, nonzero, indices, ones, nx
34- #from matplotlib._pylab_helpers import Gcf
32+ from matplotlib .numerix import asarray , pi , fromstring , UInt8 , zeros
33+ # where, transpose, nonzero, indices, ones, nx
34+ #from matplotlib._matlab_helpers import Gcf
35+ import matplotlib .numerix as numerix
36+
3537from matplotlib .backend_bases import RendererBase , GraphicsContextBase ,\
3638 FigureManagerBase , FigureCanvasBase , error_msg
3739from matplotlib .cbook import enumerate , True , False
3840from matplotlib .figure import Figure
3941from matplotlib .transforms import Bbox
42+ from matplotlib .mathtext import math_parse_s_ft2font
4043
4144import cairo
4245
@@ -224,27 +227,77 @@ def draw_rectangle(self, gc, rgbFace, x, y, width, height):
224227
225228 def draw_text (self , gc , x , y , s , prop , angle , ismath = False ):
226229 if DEBUG : print 'backend_cairo.RendererCairo.%s()' % _fn_name ()
227- ctx = gc .ctx
228230
229231 if ismath :
230- verbose .report_error ('Mathtext not implemented yet' )
232+ self ._draw_mathtext (gc , x , y , s , prop , angle )
233+
231234 else :
232- ctx .new_path ()
233- ctx .move_to (x , y )
234- ctx .select_font (prop .get_name (),
235- self .fontangles [prop .get_style ()],
236- self .fontweights [prop .get_weight ()])
237- # 1.4 scales font to a similar size to GTK / GTKAgg backends
238- size = prop .get_size_in_points () * self .dpi .get () / PIXELS_PER_INCH * 1.4
235+ ctx = gc .ctx
236+ ctx .new_path ()
237+ ctx .move_to (x , y )
238+ ctx .select_font (prop .get_name (),
239+ self .fontangles [prop .get_style ()],
240+ self .fontweights [prop .get_weight ()])
241+ # 1.4 scales font to a similar size to GTK / GTKAgg backends
242+ size = prop .get_size_in_points () * self .dpi .get () / PIXELS_PER_INCH * 1.4
243+
244+ ctx .save ()
245+ if angle :
246+ ctx .rotate (- angle * pi / 180 )
247+ ctx .scale_font (size )
248+ ctx .show_text (s )
249+ ctx .restore ()
250+
251+
252+ def _draw_mathtext (self , gc , x , y , s , prop , angle ):
253+ if DEBUG : print 'backend_cairo.RendererCairo.%s()' % _fn_name ()
254+ # mathtext using the gtk/gdk method
239255
240- ctx .save ()
241- if angle :
242- ctx .rotate (- angle * pi / 180 )
243- ctx .scale_font (size )
244- ctx .show_text (s )
245- ctx .restore ()
256+ try : import cairo .numpy
257+ except :
258+ verbose .report_error ("cairo.numpy module required for _draw_mathtext()" )
259+ return
260+
261+ size = prop .get_size_in_points ()
262+ width , height , fonts = math_parse_s_ft2font (
263+ s , self .dpi .get (), size )
264+
265+ if angle == 90 :
266+ width , height = height , width
267+ x -= width
268+ y -= height
269+
270+ imw , imh , s = fonts [0 ].image_as_str ()
271+ N = imw * imh
272+
273+ # a numpixels by num fonts array
274+ Xall = zeros ((N ,len (fonts )), typecode = UInt8 )
275+
276+ for i , font in enumerate (fonts ):
277+ if angle == 90 :
278+ font .horiz_image_to_vert_image () # <-- Rotate
279+ imw , imh , s = font .image_as_str ()
280+ Xall [:,i ] = fromstring (s , UInt8 )
281+
282+ # get the max alpha at each pixel
283+ Xs = numerix .max (Xall ,1 )
284+
285+ # convert it to it's proper shape
286+ Xs .shape = imh , imw
287+
288+ pa = zeros (shape = (imh ,imw ,4 ), typecode = UInt8 )
289+ rgb = gc .get_rgb ()
290+ pa [:,:,0 ] = int (rgb [0 ]* 255 )
291+ pa [:,:,1 ] = int (rgb [1 ]* 255 )
292+ pa [:,:,2 ] = int (rgb [2 ]* 255 )
293+ pa [:,:,3 ] = Xs
294+
295+ surface = cairo .numpy .surface_create_for_array (pa )
296+ gc .ctx .translate (x ,y )
297+ gc .ctx .show_surface (surface , imw , imh )
298+ # should really restore state before translate?
299+
246300
247-
248301 def flipy (self ):
249302 if DEBUG : print 'backend_cairo.RendererCairo.%s()' % _fn_name ()
250303 return True
@@ -258,26 +311,27 @@ def get_canvas_width_height(self):
258311 def get_text_width_height (self , s , prop , ismath ):
259312 if DEBUG : print 'backend_cairo.RendererCairo.%s()' % _fn_name ()
260313 if ismath :
261- print 'ismath get_text_width_height() not implemented yet'
262- return 1 , 1
263- else :
264- ctx = self .text_ctx
265- ctx .save ()
266- ctx .select_font (prop .get_name (),
267- self .fontangles [prop .get_style ()],
268- self .fontweights [prop .get_weight ()])
269-
270- # 1.4 scales font to a similar size to GTK / GTKAgg backends
271- size = prop .get_size_in_points () * self .dpi .get () / PIXELS_PER_INCH * 1.4
272- # problem - scale remembers last setting and font can become
273- # enormous causing program to crash
274- # save/restore prevents the problem
275- ctx .scale_font (size )
314+ width , height , fonts = math_parse_s_ft2font (
315+ s , self .dpi .get (), prop .get_size_in_points ())
316+ return width , height
317+
318+ ctx = self .text_ctx
319+ ctx .save ()
320+ ctx .select_font (prop .get_name (),
321+ self .fontangles [prop .get_style ()],
322+ self .fontweights [prop .get_weight ()])
323+
324+ # 1.4 scales font to a similar size to GTK / GTKAgg backends
325+ size = prop .get_size_in_points () * self .dpi .get () / PIXELS_PER_INCH * 1.4
326+ # problem - scale remembers last setting and font can become
327+ # enormous causing program to crash
328+ # save/restore prevents the problem
329+ ctx .scale_font (size )
276330
277- w , h = ctx .text_extents (s )[2 :4 ]
278- ctx .restore ()
331+ w , h = ctx .text_extents (s )[2 :4 ]
332+ ctx .restore ()
279333
280- return w , h
334+ return w , h
281335
282336
283337 def new_gc (self ):
0 commit comments