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

Skip to content

Commit c7f9008

Browse files
committed
add TextPath class in text.py. Update demo_text_path.py
svn path=/trunk/matplotlib/; revision=7606
1 parent 61c08f3 commit c7f9008

2 files changed

Lines changed: 216 additions & 134 deletions

File tree

examples/pylab_examples/demo_text_path.py

Lines changed: 40 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -4,147 +4,54 @@
44
import matplotlib.pyplot as plt
55
from matplotlib.image import BboxImage
66
import numpy as np
7-
from matplotlib.transforms import Affine2D, IdentityTransform
7+
from matplotlib.transforms import IdentityTransform
88

9-
import matplotlib.font_manager as font_manager
10-
from matplotlib.ft2font import FT2Font, KERNING_DEFAULT, LOAD_NO_HINTING
11-
from matplotlib.font_manager import FontProperties
12-
from matplotlib.path import Path
139
import matplotlib.patches as mpatches
1410

1511
from matplotlib.offsetbox import AnnotationBbox,\
1612
AnchoredOffsetbox, AuxTransformBox
1713

18-
#from matplotlib.offsetbox import
19-
2014
from matplotlib.cbook import get_sample_data
2115

16+
from matplotlib.text import TextPath
2217

23-
class TextPatch(mpatches.PathPatch):
24-
25-
FONT_SCALE = 100.
26-
27-
def __init__(self, xy, s, size=None, prop=None, bbox_image=None,
28-
*kl, **kwargs):
29-
if prop is None:
30-
prop = FontProperties()
31-
32-
if size is None:
33-
size = prop.get_size_in_points()
34-
35-
self._xy = xy
36-
self.set_size(size)
3718

38-
self.text_path = self.text_get_path(prop, s)
39-
40-
mpatches.PathPatch.__init__(self, self.text_path, *kl, **kwargs)
19+
class PathClippedImagePatch(mpatches.PathPatch):
20+
"""
21+
The given image is used to draw the face of the patch. Internally,
22+
it uses BboxImage whose clippath set to the path of the patch.
4123
24+
FIXME : The result is currently dpi dependent.
25+
"""
26+
def __init__(self, path, bbox_image, **kwargs):
27+
mpatches.PathPatch.__init__(self, path, **kwargs)
28+
self._facecolor = "none"
4229
self._init_bbox_image(bbox_image)
4330

44-
31+
def set_facecolor(self, color):
32+
pass
33+
4534
def _init_bbox_image(self, im):
4635

47-
if im is None:
48-
self.bbox_image = None
49-
else:
50-
bbox_image = BboxImage(self.get_window_extent,
51-
norm = None,
52-
origin=None,
53-
)
54-
bbox_image.set_transform(IdentityTransform())
36+
bbox_image = BboxImage(self.get_window_extent,
37+
norm = None,
38+
origin=None,
39+
)
40+
bbox_image.set_transform(IdentityTransform())
5541

56-
bbox_image.set_data(im)
57-
self.bbox_image = bbox_image
42+
bbox_image.set_data(im)
43+
self.bbox_image = bbox_image
5844

5945
def draw(self, renderer=None):
6046

6147

62-
if self.bbox_image is not None:
63-
# the clip path must be updated every draw. any solution? -JJ
64-
self.bbox_image.set_clip_path(self.text_path, self.get_transform())
65-
self.bbox_image.draw(renderer)
48+
# the clip path must be updated every draw. any solution? -JJ
49+
self.bbox_image.set_clip_path(self._path, self.get_transform())
50+
self.bbox_image.draw(renderer)
6651

6752
mpatches.PathPatch.draw(self, renderer)
6853

6954

70-
def set_size(self, size):
71-
self._size = size
72-
73-
def get_size(self):
74-
return self._size
75-
76-
def get_patch_transform(self):
77-
tr = Affine2D().scale(self._size/self.FONT_SCALE, self._size/self.FONT_SCALE)
78-
return tr.translate(*self._xy)
79-
80-
def glyph_char_path(self, glyph, currx=0.):
81-
82-
verts, codes = [], []
83-
for step in glyph.path:
84-
if step[0] == 0: # MOVE_TO
85-
verts.append((step[1], step[2]))
86-
codes.append(Path.MOVETO)
87-
elif step[0] == 1: # LINE_TO
88-
verts.append((step[1], step[2]))
89-
codes.append(Path.LINETO)
90-
elif step[0] == 2: # CURVE3
91-
verts.extend([(step[1], step[2]),
92-
(step[3], step[4])])
93-
codes.extend([Path.CURVE3, Path.CURVE3])
94-
elif step[0] == 3: # CURVE4
95-
verts.extend([(step[1], step[2]),
96-
(step[3], step[4]),
97-
(step[5], step[6])])
98-
codes.extend([Path.CURVE4, Path.CURVE4, Path.CURVE4])
99-
elif step[0] == 4: # ENDPOLY
100-
verts.append((0, 0,))
101-
codes.append(Path.CLOSEPOLY)
102-
103-
verts = [(x+currx, y) for (x,y) in verts]
104-
105-
return verts, codes
106-
107-
108-
def text_get_path(self, prop, s):
109-
110-
fname = font_manager.findfont(prop)
111-
font = FT2Font(str(fname))
112-
113-
font.set_size(self.FONT_SCALE, 72)
114-
115-
cmap = font.get_charmap()
116-
lastgind = None
117-
118-
currx = 0
119-
120-
verts, codes = [], []
121-
122-
for c in s:
123-
124-
ccode = ord(c)
125-
gind = cmap.get(ccode)
126-
if gind is None:
127-
ccode = ord('?')
128-
gind = 0
129-
glyph = font.load_char(ccode, flags=LOAD_NO_HINTING)
130-
131-
132-
if lastgind is not None:
133-
kern = font.get_kerning(lastgind, gind, KERNING_DEFAULT)
134-
else:
135-
kern = 0
136-
currx += (kern / 64.0) #/ (self.FONT_SCALE)
137-
138-
verts1, codes1 = self.glyph_char_path(glyph, currx)
139-
verts.extend(verts1)
140-
codes.extend(codes1)
141-
142-
143-
currx += (glyph.linearHoriAdvance / 65536.0) #/ (self.FONT_SCALE)
144-
lastgind = gind
145-
146-
return Path(verts, codes)
147-
14855
if 1:
14956

15057
fig = plt.figure(1)
@@ -156,10 +63,12 @@ def text_get_path(self, prop, s):
15663
from matplotlib._png import read_png
15764
fn = get_sample_data("lena.png", asfileobj=False)
15865
arr = read_png(fn)
159-
p = TextPatch((0, 0), "!?", size=150, fc="none", ec="k",
160-
bbox_image=arr,
161-
transform=IdentityTransform())
162-
p.set_clip_on(False)
66+
67+
text_path = TextPath((0, 0), "!?", size=150)
68+
p = PathClippedImagePatch(text_path, arr, ec="k",
69+
transform=IdentityTransform())
70+
71+
#p.set_clip_on(False)
16372

16473
# make offset box
16574
offsetbox = AuxTransformBox(IdentityTransform())
@@ -176,38 +85,35 @@ def text_get_path(self, prop, s):
17685

17786
ax = plt.subplot(212)
17887

179-
shadow1 = TextPatch((3, -2), "TextPath", size=70, fc="none", ec="0.6", lw=3,
180-
transform=IdentityTransform())
181-
shadow2 = TextPatch((3, -2), "TextPath", size=70, fc="0.3", ec="none",
182-
transform=IdentityTransform())
183-
18488
arr = np.arange(256).reshape(1,256)/256.
185-
text_path = TextPatch((0, 0), "TextPath", size=70, fc="none", ec="none", lw=1,
186-
bbox_image=arr,
187-
transform=IdentityTransform())
89+
90+
text_path = TextPath((0, 0), "TextPath", size=70)
91+
text_patch = PathClippedImagePatch(text_path, arr, ec="none",
92+
transform=IdentityTransform())
93+
94+
shadow1 = mpatches.Shadow(text_patch, 3, -2, props=dict(fc="none", ec="0.6", lw=3))
95+
shadow2 = mpatches.Shadow(text_patch, 3, -2, props=dict(fc="0.3", ec="none"))
96+
18897

18998
# make offset box
19099
offsetbox = AuxTransformBox(IdentityTransform())
191100
offsetbox.add_artist(shadow1)
192101
offsetbox.add_artist(shadow2)
193-
offsetbox.add_artist(text_path)
102+
offsetbox.add_artist(text_patch)
194103

195104
# place the anchored offset box using AnnotationBbox
196105
ab = AnnotationBbox(offsetbox, (0.5, 0.5),
197106
xycoords='data',
198107
boxcoords="offset points",
199108
box_alignment=(0.5,0.5),
200109
)
201-
110+
#text_path.set_size(10)
202111

203112
ax.add_artist(ab)
204113

205114
ax.set_xlim(0, 1)
206115
ax.set_ylim(0, 1)
207116

208117

209-
210-
211-
212118
plt.draw()
213119
plt.show()

0 commit comments

Comments
 (0)