Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5030f23

Browse files
committed
applied sf patch 2853659
svn path=/trunk/matplotlib/; revision=7706
1 parent 6bac443 commit 5030f23

1 file changed

Lines changed: 118 additions & 8 deletions

File tree

lib/matplotlib/backends/backend_emf.py

Lines changed: 118 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
from matplotlib.font_manager import findfont, FontProperties
2424
from matplotlib.ft2font import FT2Font, KERNING_UNFITTED, KERNING_DEFAULT, KERNING_UNSCALED
2525

26+
from matplotlib.path import Path
27+
from matplotlib.transforms import Affine2D
28+
from matplotlib.mlab import quad2cubic
29+
2630
# Font handling stuff snarfed from backend_ps, but only using TTF fonts
2731
_fontd = {}
2832

@@ -81,7 +85,7 @@ def set_linestyle(self):
8185
'dashdot':pyemf.PS_DASHDOT, 'dotted':pyemf.PS_DOT}
8286
#style=styles.get(self.gc.get_linestyle('solid'))
8387
style=self.gc.get_linestyle('solid')
84-
if debugHandle: print "EMFPen: style=%d" % style
88+
if debugHandle: print "EMFPen: style=%s" % style
8589
if style in styles:
8690
self.style=styles[style]
8791
else:
@@ -116,6 +120,28 @@ class RendererEMF(RendererBase):
116120
The renderer handles drawing/rendering operations through a
117121
pyemf.EMF instance.
118122
"""
123+
124+
fontweights = {
125+
100 : pyemf.FW_NORMAL,
126+
200 : pyemf.FW_NORMAL,
127+
300 : pyemf.FW_NORMAL,
128+
400 : pyemf.FW_NORMAL,
129+
500 : pyemf.FW_NORMAL,
130+
600 : pyemf.FW_BOLD,
131+
700 : pyemf.FW_BOLD,
132+
800 : pyemf.FW_BOLD,
133+
900 : pyemf.FW_BOLD,
134+
'ultralight' : pyemf.FW_ULTRALIGHT,
135+
'light' : pyemf.FW_LIGHT,
136+
'normal' : pyemf.FW_NORMAL,
137+
'medium' : pyemf.FW_MEDIUM,
138+
'semibold' : pyemf.FW_SEMIBOLD,
139+
'bold' : pyemf.FW_BOLD,
140+
'heavy' : pyemf.FW_HEAVY,
141+
'ultrabold' : pyemf.FW_ULTRABOLD,
142+
'black' : pyemf.FW_BLACK,
143+
}
144+
119145
def __init__(self, outfile, width, height, dpi):
120146
"Initialize the renderer with a gd image instance"
121147
self.outfile = outfile
@@ -141,6 +167,8 @@ def __init__(self, outfile, width, height, dpi):
141167
# set baseline for text to be bottom left corner
142168
self.emf.SetTextAlign( pyemf.TA_BOTTOM|pyemf.TA_LEFT)
143169

170+
self._lastClipRect = None
171+
144172
if debugPrint: print "RendererEMF: (%f,%f) %s dpi=%f" % (self.width,self.height,outfile,dpi)
145173

146174

@@ -176,7 +204,65 @@ def draw_arc(self, gcEdge, rgbFace, x, y, width, height, angle1, angle2, rotatio
176204
self.emf.Arc(int(x-hw),int(self.height-(y-hh)),int(x+hw),int(self.height-(y+hh)),int(x+math.cos(angle1*math.pi/180.0)*hw),int(self.height-(y+math.sin(angle1*math.pi/180.0)*hh)),int(x+math.cos(angle2*math.pi/180.0)*hw),int(self.height-(y+math.sin(angle2*math.pi/180.0)*hh)))
177205

178206

179-
def draw_image(self, x, y, im, bbox):
207+
def handle_clip_rectangle(self, gc):
208+
new_bounds = gc.get_clip_rectangle()
209+
if new_bounds is not None:
210+
new_bounds = new_bounds.bounds
211+
if self._lastClipRect != new_bounds:
212+
self._lastClipRect = new_bounds
213+
if new_bounds is None:
214+
# use the maximum rectangle to disable clipping
215+
x, y, width, height = (0, 0, self.width, self.height)
216+
else:
217+
x, y, width, height = new_bounds
218+
self.emf.BeginPath()
219+
self.emf.MoveTo(int(x), int(self.height - y))
220+
self.emf.LineTo(int(x) + int(width), int(self.height - y))
221+
self.emf.LineTo(int(x) + int(width), int(self.height - y) - int(height))
222+
self.emf.LineTo(int(x), int(self.height - y) - int(height))
223+
self.emf.CloseFigure()
224+
self.emf.EndPath()
225+
self.emf.SelectClipPath()
226+
227+
228+
def convert_path(self, tpath):
229+
self.emf.BeginPath()
230+
last_points = None
231+
for points, code in tpath.iter_segments():
232+
if code == Path.MOVETO:
233+
self.emf.MoveTo(*points)
234+
elif code == Path.LINETO:
235+
self.emf.LineTo(*points)
236+
elif code == Path.CURVE3:
237+
points = quad2cubic(*(list(last_points[-2:]) + list(points)))
238+
self.emf.PolyBezierTo(zip(points[2::2], points[3::2]))
239+
elif code == Path.CURVE4:
240+
self.emf.PolyBezierTo(zip(points[::2], points[1::2]))
241+
elif code == Path.CLOSEPOLY:
242+
self.emf.CloseFigure()
243+
last_points = points
244+
self.emf.EndPath()
245+
246+
247+
def draw_path(self, gc, path, transform, rgbFace=None):
248+
"""
249+
Draws a :class:`~matplotlib.path.Path` instance using the
250+
given affine transform.
251+
"""
252+
self.handle_clip_rectangle(gc)
253+
gc._rgb = gc._rgb[:3]
254+
self.select_pen(gc)
255+
self.select_brush(rgbFace)
256+
transform = transform + Affine2D().scale(1.0, -1.0).translate(0.0, self.height)
257+
tpath = transform.transform_path(path)
258+
self.convert_path(tpath)
259+
if rgbFace is None:
260+
self.emf.StrokePath()
261+
else:
262+
self.emf.StrokeAndFillPath()
263+
264+
265+
def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
180266
"""
181267
Draw the Image instance into the current axes; x is the
182268
distance in pixels from the left hand side of the canvas. y is
@@ -285,11 +371,17 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
285371
to if 1, and then the actual bounding box will be blotted along with
286372
your text.
287373
"""
288-
if debugText: print "draw_text: (%f,%f) %d degrees: '%s'" % (x,y,angle,s)
289-
if ismath:
290-
self.draw_math_text(gc,x,y,s,prop,angle)
291-
else:
292-
self.draw_plain_text(gc,x,y,s,prop,angle)
374+
if ismath: s = self.strip_math(s)
375+
self.handle_clip_rectangle(gc)
376+
self.emf.SetTextColor(gc.get_rgb()[:3])
377+
self.select_font(prop,angle)
378+
if isinstance(s, unicode):
379+
# unicode characters do not seem to work with pyemf
380+
try:
381+
s = s.replace(u'\u2212', '-').encode('iso-8859-1')
382+
except UnicodeEncodeError:
383+
pass
384+
self.emf.TextOut(x,y,s)
293385

294386

295387
def draw_plain_text(self, gc, x, y, s, prop, angle):
@@ -369,6 +461,22 @@ def get_math_text_width_height(self, s, prop):
369461
return w, h
370462

371463

464+
def get_text_width_height_descent(self, s, prop, ismath):
465+
"""
466+
get the width and height in display coords of the string s
467+
with FontPropertry prop
468+
"""
469+
if ismath: s = self.strip_math(s)
470+
font = self._get_font_ttf(prop)
471+
font.set_text(s, 0.0)
472+
w, h = font.get_width_height()
473+
w /= 64.0 # convert from subpixels
474+
h /= 64.0
475+
d = font.get_descent()
476+
d /= 64.0
477+
return w, h, d
478+
479+
372480
def flipy(self):
373481
"""return true if y small numbers are top for renderer
374482
Is used for drawing text (text.py) and images (image.py) only
@@ -407,7 +515,9 @@ def get_font_handle(self, prop, angle):
407515
handle = self._fontHandle.get(key)
408516
if handle is None:
409517
handle=self.emf.CreateFont(-size, 0, int(angle)*10, int(angle)*10,
410-
pyemf.FW_NORMAL, 0, 0, 0,
518+
self.fontweights.get(prop.get_weight(), pyemf.FW_NORMAL),
519+
int(prop.get_style() == 'italic'),
520+
0, 0,
411521
pyemf.ANSI_CHARSET, pyemf.OUT_DEFAULT_PRECIS,
412522
pyemf.CLIP_DEFAULT_PRECIS, pyemf.DEFAULT_QUALITY,
413523
pyemf.DEFAULT_PITCH | pyemf.FF_DONTCARE, face);

0 commit comments

Comments
 (0)