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

Skip to content

Commit 835c4ac

Browse files
committed
textpath support mathtext and tex
svn path=/trunk/matplotlib/; revision=7635
1 parent bb29f57 commit 835c4ac

7 files changed

Lines changed: 578 additions & 174 deletions

File tree

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
2009-09-04 Make the textpath class as a separate moduel
2+
(textpath.py). Add support for mathtext and tex.- JJL
3+
14
2009-09-01 Added support for Gouraud interpolated triangles.
25
pcolormesh now accepts shading='gouraud' as an option. - MGD
36

examples/pylab_examples/demo_text_path.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,33 @@ def draw(self, renderer=None):
7676

7777
# make anchored offset box
7878
ao = AnchoredOffsetbox(loc=2, child=offsetbox, frameon=True, borderpad=0.2)
79-
8079
ax.add_artist(ao)
8180

81+
# another text
82+
from matplotlib.patches import PathPatch
83+
text_path = TextPath((0, 0), r"\mbox{textpath supports mathtext \& \TeX}",
84+
size=20, usetex=True)
85+
p1 = PathPatch(text_path, ec="w", lw=3, fc="w", alpha=0.9,
86+
transform=IdentityTransform())
87+
p2 = PathPatch(text_path, ec="none", fc="k",
88+
transform=IdentityTransform())
89+
90+
offsetbox2 = AuxTransformBox(IdentityTransform())
91+
offsetbox2.add_artist(p1)
92+
offsetbox2.add_artist(p2)
93+
94+
ab = AnnotationBbox(offsetbox2, (0.95, 0.05),
95+
xycoords='axes fraction',
96+
boxcoords="offset points",
97+
box_alignment=(1.,0.),
98+
frameon=False
99+
)
100+
ax.add_artist(ab)
101+
102+
ax.imshow([[0,1,2],[1,2,3]], cmap=plt.cm.gist_gray_r,
103+
interpolation="bilinear",
104+
aspect="auto")
105+
82106

83107

84108
# EXAMPLE 2
@@ -87,12 +111,17 @@ def draw(self, renderer=None):
87111

88112
arr = np.arange(256).reshape(1,256)/256.
89113

90-
text_path = TextPath((0, 0), "TextPath", size=70)
114+
usetex = plt.rcParams["text.usetex"]
115+
if usetex:
116+
s = r"$\displaystyle\left[\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}\right]$!"
117+
else:
118+
s = r"$\left[\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}\right]$!"
119+
text_path = TextPath((0, 0), s, size=40, usetex=usetex)
91120
text_patch = PathClippedImagePatch(text_path, arr, ec="none",
92121
transform=IdentityTransform())
93122

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"))
123+
shadow1 = mpatches.Shadow(text_patch, 1, -1, props=dict(fc="none", ec="0.6", lw=3))
124+
shadow2 = mpatches.Shadow(text_patch, 1, -1, props=dict(fc="0.3", ec="none"))
96125

97126

98127
# make offset box

lib/matplotlib/mathtext.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,34 @@ def get_results(self, box):
336336
svg_elements,
337337
self.fonts_object.get_used_characters())
338338

339+
class MathtextBackendPath(MathtextBackend):
340+
"""
341+
Store information to write a mathtext rendering to the Cairo
342+
backend.
343+
"""
344+
345+
def __init__(self):
346+
self.glyphs = []
347+
self.rects = []
348+
349+
def render_glyph(self, ox, oy, info):
350+
oy = self.height - oy + info.offset
351+
thetext = unichr(info.num)
352+
self.glyphs.append(
353+
(info.font, info.fontsize, thetext, ox, oy))
354+
355+
def render_rect_filled(self, x1, y1, x2, y2):
356+
self.rects.append(
357+
(x1, self.height-y2 , x2 - x1, y2 - y1))
358+
359+
def get_results(self, box):
360+
ship(0, -self.depth, box)
361+
return (self.width,
362+
self.height + self.depth,
363+
self.depth,
364+
self.glyphs,
365+
self.rects)
366+
339367
class MathtextBackendCairo(MathtextBackend):
340368
"""
341369
Store information to write a mathtext rendering to the Cairo
@@ -2751,6 +2779,7 @@ class MathTextParser(object):
27512779
'ps' : MathtextBackendPs,
27522780
'pdf' : MathtextBackendPdf,
27532781
'svg' : MathtextBackendSvg,
2782+
'path' : MathtextBackendPath,
27542783
'cairo' : MathtextBackendCairo,
27552784
'macosx': MathtextBackendAgg,
27562785
}

lib/matplotlib/text.py

Lines changed: 1 addition & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,173 +1770,4 @@ def draw(self, renderer):
17701770
docstring.interpd.update(Annotation=Annotation.__init__.__doc__)
17711771

17721772

1773-
class TextPath(Path):
1774-
"""
1775-
Create a path from the text.
1776-
"""
1777-
1778-
# TODO : math text is currently not supported, but it would not be easy.
1779-
1780-
FONT_SCALE = 100.
1781-
1782-
def __init__(self, xy, s, size=None, prop=None,
1783-
_interpolation_steps=1,
1784-
*kl, **kwargs):
1785-
"""
1786-
Create a path from the text. No support for TeX yet. Note that
1787-
it simply is a path, not an artist. You need to use the
1788-
PathPatch (or other artists) to draw this path onto the
1789-
canvas.
1790-
1791-
xy : position of the text.
1792-
s : text
1793-
size : font size
1794-
prop : font property
1795-
"""
1796-
1797-
1798-
if prop is None:
1799-
prop = FontProperties()
1800-
1801-
if size is None:
1802-
size = prop.get_size_in_points()
1803-
1804-
1805-
self._xy = xy
1806-
self.set_size(size)
1807-
1808-
self._cached_vertices = None
1809-
1810-
self._vertices, self._codes = self.text_get_vertices_codes(prop, s)
1811-
1812-
self.should_simplify = False
1813-
self.simplify_threshold = rcParams['path.simplify_threshold']
1814-
self.has_nonfinite = False
1815-
self._interpolation_steps = _interpolation_steps
1816-
1817-
1818-
def set_size(self, size):
1819-
"""
1820-
set the size of the text
1821-
"""
1822-
self._size = size
1823-
self._invalid = True
1824-
1825-
def get_size(self):
1826-
"""
1827-
get the size of the text
1828-
"""
1829-
return self._size
1830-
1831-
def _get_vertices(self):
1832-
"""
1833-
Return the cached path after updating it if necessary.
1834-
"""
1835-
self._revalidate_path()
1836-
return self._cached_vertices
1837-
1838-
def _get_codes(self):
1839-
"""
1840-
Return the codes
1841-
"""
1842-
return self._codes
1843-
1844-
vertices = property(_get_vertices)
1845-
codes = property(_get_codes)
1846-
1847-
def _revalidate_path(self):
1848-
"""
1849-
update the path if necessary.
1850-
1851-
The path for the text is initially create with the font size
1852-
of FONT_SCALE, and this path is rescaled to other size when
1853-
necessary.
1854-
1855-
"""
1856-
if self._invalid or \
1857-
(self._cached_vertices is None):
1858-
tr = Affine2D().scale(self._size/self.FONT_SCALE,
1859-
self._size/self.FONT_SCALE).translate(*self._xy)
1860-
self._cached_vertices = tr.transform(self._vertices)
1861-
self._invalid = False
1862-
1863-
1864-
def glyph_char_path(self, glyph, currx=0.):
1865-
"""
1866-
convert the glyph to vertices and codes. Mostly copied from
1867-
backend_svg.py.
1868-
"""
1869-
verts, codes = [], []
1870-
for step in glyph.path:
1871-
if step[0] == 0: # MOVE_TO
1872-
verts.append((step[1], step[2]))
1873-
codes.append(Path.MOVETO)
1874-
elif step[0] == 1: # LINE_TO
1875-
verts.append((step[1], step[2]))
1876-
codes.append(Path.LINETO)
1877-
elif step[0] == 2: # CURVE3
1878-
verts.extend([(step[1], step[2]),
1879-
(step[3], step[4])])
1880-
codes.extend([Path.CURVE3, Path.CURVE3])
1881-
elif step[0] == 3: # CURVE4
1882-
verts.extend([(step[1], step[2]),
1883-
(step[3], step[4]),
1884-
(step[5], step[6])])
1885-
codes.extend([Path.CURVE4, Path.CURVE4, Path.CURVE4])
1886-
elif step[0] == 4: # ENDPOLY
1887-
verts.append((0, 0,))
1888-
codes.append(Path.CLOSEPOLY)
1889-
1890-
verts = [(x+currx, y) for (x,y) in verts]
1891-
1892-
return verts, codes
1893-
1894-
1895-
def text_get_vertices_codes(self, prop, s):
1896-
"""
1897-
convert the string *s* to vertices and codes using the
1898-
provided font property *prop*. Mostly copied from
1899-
backend_svg.py.
1900-
"""
1901-
1902-
fname = font_manager.findfont(prop)
1903-
font = FT2Font(str(fname))
1904-
1905-
font.set_size(self.FONT_SCALE, 72)
1906-
1907-
cmap = font.get_charmap()
1908-
lastgind = None
1909-
1910-
currx = 0
1911-
1912-
verts, codes = [], []
1913-
1914-
1915-
# I'm not sure if I get kernings right. Needs to be verified. -JJL
1916-
1917-
for c in s:
1918-
1919-
ccode = ord(c)
1920-
gind = cmap.get(ccode)
1921-
if gind is None:
1922-
ccode = ord('?')
1923-
gind = 0
1924-
glyph = font.load_char(ccode, flags=LOAD_NO_HINTING)
1925-
1926-
1927-
if lastgind is not None:
1928-
kern = font.get_kerning(lastgind, gind, KERNING_DEFAULT)
1929-
else:
1930-
kern = 0
1931-
currx += (kern / 64.0) #/ (self.FONT_SCALE)
1932-
1933-
verts1, codes1 = self.glyph_char_path(glyph, currx)
1934-
verts.extend(verts1)
1935-
codes.extend(codes1)
1936-
1937-
1938-
currx += (glyph.linearHoriAdvance / 65536.0) #/ (self.FONT_SCALE)
1939-
lastgind = gind
1940-
1941-
return verts, codes
1942-
1773+
from matplotlib.textpath import TextPath

0 commit comments

Comments
 (0)