SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

You can subscribe to this list here.

2007 Jan
Feb
Mar
Apr
May
Jun
Jul
(115)
Aug
(120)
Sep
(137)
Oct
(170)
Nov
(461)
Dec
(263)
2008 Jan
(120)
Feb
(74)
Mar
(35)
Apr
(74)
May
(245)
Jun
(356)
Jul
(240)
Aug
(115)
Sep
(78)
Oct
(225)
Nov
(98)
Dec
(271)
2009 Jan
(132)
Feb
(84)
Mar
(74)
Apr
(56)
May
(90)
Jun
(79)
Jul
(83)
Aug
(296)
Sep
(214)
Oct
(76)
Nov
(82)
Dec
(66)
2010 Jan
(46)
Feb
(58)
Mar
(51)
Apr
(77)
May
(58)
Jun
(126)
Jul
(128)
Aug
(64)
Sep
(50)
Oct
(44)
Nov
(48)
Dec
(54)
2011 Jan
(68)
Feb
(52)
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
(1)
2018 Jan
Feb
Mar
Apr
May
(1)
Jun
Jul
Aug
Sep
Oct
Nov
Dec
S M T W T F S

1
(7)
2
(14)
3
(6)
4
(8)
5
(6)
6
(3)
7
(2)
8
(22)
9
(9)
10
(23)
11
(14)
12
(22)
13
(7)
14
(3)
15
(22)
16
(13)
17
(18)
18
(21)
19
(9)
20
21
(3)
22
(6)
23
(5)
24
25
26
(3)
27
28
(1)
29
(11)
30
(1)
31
(12)



Showing results of 271

1 2 3 .. 11 > >> (Page 1 of 11)
Revision: 6729
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6729&view=rev
Author: jswhit
Date: 2008年12月31日 20:19:16 +0000 (2008年12月31日)
Log Message:
-----------
fix small bug in land-sea mask lat/lon definitions
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 19:56:55 UTC (rev 6728)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 20:19:16 UTC (rev 6729)
@@ -3110,9 +3110,16 @@
 lsmaskf = open(os.path.join(basemap_datadir,'5minmask.bin'),'rb')
 nlons = 4320; nlats = nlons/2
 delta = 360./float(nlons)
- lsmask_lons = np.arange(-180+0.5*delta,180.,delta)
- lsmask_lats = np.arange(-90.+0.5*delta,90.,delta)
 lsmask = np.reshape(np.fromstring(lsmaskf.read(),np.uint8),(nlats,nlons))
+ lsmask_lons = np.arange(-180,180.,delta)
+ lsmask_lats = np.arange(-90.,90+0.5*delta,delta)
+ # add cyclic point in longitude
+ lsmask, lsmask_lons = addcyclic(lsmask, lsmask_lons)
+ nlons = nlons + 1; nlats = nlats + 1
+ # add North Pole point (assumed water)
+ tmparr = np.zeros((nlats,nlons),lsmask.dtype)
+ tmparr[0:nlats-1,0:nlons] = lsmask
+ lsmask = tmparr
 lsmaskf.close()
 # instance variable lsmask is set on first invocation,
 # it contains the land-sea mask interpolated to the native
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6728
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6728&view=rev
Author: jouni
Date: 2008年12月31日 19:56:55 +0000 (2008年12月31日)
Log Message:
-----------
Don't crash with Microsoft fonts such as Tahoma
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月31日 19:42:44 UTC (rev 6727)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月31日 19:56:55 UTC (rev 6728)
@@ -333,7 +333,7 @@
 self.file.write(compressed)
 self.compressobj = None
 
-class PdfFile:
+class PdfFile(object):
 """PDF file with one page."""
 
 def __init__(self, width, height, dpi, filename):
@@ -900,7 +900,14 @@
 # Beginning of main embedTTF function...
 
 # You are lost in a maze of TrueType tables, all different...
- ps_name = Name(font.get_sfnt()[(1,0,0,6)])
+ sfnt = font.get_sfnt()
+ try:
+ ps_name = sfnt[(1,0,0,6)] # Macintosh scheme
+ except KeyError:
+ # Microsoft scheme:
+ ps_name = sfnt[(3,1,0x0409,6)].decode('utf-16be').encode('ascii','replace')
+ # (see freetype/ttnameid.h)
+ ps_name = Name(ps_name)
 pclt = font.get_sfnt_table('pclt') \
 or { 'capHeight': 0, 'xHeight': 0 }
 post = font.get_sfnt_table('post') \
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6727
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6727&view=rev
Author: jouni
Date: 2008年12月31日 19:42:44 +0000 (2008年12月31日)
Log Message:
-----------
Modernize a little since we can assume Python 2.4
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月31日 19:01:41 UTC (rev 6726)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月31日 19:42:44 UTC (rev 6727)
@@ -185,7 +185,7 @@
 "Don't know a PDF representation for %s objects." \
 % type(obj)
 
-class Reference:
+class Reference(object):
 """PDF reference object.
 Use PdfFile.reserveObject() to create References.
 """
@@ -205,8 +205,9 @@
 write(pdfRepr(contents))
 write("\nendobj\n")
 
-class Name:
+class Name(object):
 """PDF name object."""
+ __slots__ = ('name',)
 _regex = re.compile(r'[^!-~]')
 
 def __init__(self, name):
@@ -218,15 +219,16 @@
 def __repr__(self):
 return "<Name %s>" % self.name
 
+ @staticmethod
 def hexify(match):
 return '#%02x' % ord(match.group())
- hexify = staticmethod(hexify)
 
 def pdfRepr(self):
 return '/' + self.name
 
-class Operator:
+class Operator(object):
 """PDF operator object."""
+ __slots__ = ('op',)
 
 def __init__(self, op):
 self.op = op
@@ -257,12 +259,13 @@
 Op = Bunch(**dict([(name, Operator(value))
 for name, value in _pdfops.items()]))
 
-class Stream:
+class Stream(object):
 """PDF stream object.
 
 This has no pdfRepr method. Instead, call begin(), then output the
 contents of the stream by calling write(), and finally call end().
 """
+ __slots__ = ('id', 'len', 'pdfFile', 'file', 'compressobj', 'extra', 'pos')
 
 def __init__(self, id, len, file, extra=None):
 """id: object id of stream; len: an unused Reference object for the
@@ -1107,7 +1110,7 @@
 self.output(Op.stroke)
 self.endStream()
 
- #@staticmethod
+ @staticmethod
 def pathOperations(path, transform, simplify=None):
 tpath = transform.transform_path(path)
 
@@ -1131,7 +1134,6 @@
 cmds.append(Op.closepath)
 last_points = points
 return cmds
- pathOperations = staticmethod(pathOperations)
 
 def writePath(self, path, transform):
 cmds = self.pathOperations(
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2008年12月31日 19:01:44
Revision: 6726
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6726&view=rev
Author: jswhit
Date: 2008年12月31日 19:01:41 +0000 (2008年12月31日)
Log Message:
-----------
add comment
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/garp.py
Modified: trunk/toolkits/basemap/examples/garp.py
===================================================================
--- trunk/toolkits/basemap/examples/garp.py	2008年12月31日 19:00:19 UTC (rev 6725)
+++ trunk/toolkits/basemap/examples/garp.py	2008年12月31日 19:01:41 UTC (rev 6726)
@@ -16,6 +16,8 @@
 lat_0 = float(raw_input('input reference lat (degrees):'))
 location = raw_input('name of location:')
 
+# no width/height or lat/lon corners specified, so whole world
+# is plotted in a circle.
 m = Basemap(resolution='c',projection='aeqd',lat_0=lat_0,lon_0=lon_0)
 
 # draw coastlines and fill continents.
@@ -27,8 +29,8 @@
 #m.drawmapboundary(fill_color='white')
 #m.drawcoastlines(linewidth=0.5)
 #m.fillcontinents(color='black',lake_color='white')
-#m.drawparallels(np.arange(-80,81,20))
-#m.drawmeridians(np.arange(-180,180,20))
+#m.drawparallels(np.arange(-80,81,20),color='0.7')
+#m.drawmeridians(np.arange(-180,180,20),color='0.7')
 
 # draw lsmask instead of drawing continents (slower, but more robust).
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2008年12月31日 19:00:24
Revision: 6725
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6725&view=rev
Author: jswhit
Date: 2008年12月31日 19:00:19 +0000 (2008年12月31日)
Log Message:
-----------
make graticule gray show the lines show up over continents.
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/garp.py
Modified: trunk/toolkits/basemap/examples/garp.py
===================================================================
--- trunk/toolkits/basemap/examples/garp.py	2008年12月31日 18:49:07 UTC (rev 6724)
+++ trunk/toolkits/basemap/examples/garp.py	2008年12月31日 19:00:19 UTC (rev 6725)
@@ -33,8 +33,8 @@
 # draw lsmask instead of drawing continents (slower, but more robust).
 
 m.drawlsmask(land_color='black',ocean_color='white',lakes=True)
-m.drawparallels(np.arange(-80,81,20))
-m.drawmeridians(np.arange(-180,180,20))
+m.drawparallels(np.arange(-80,81,20),color='0.7')
+m.drawmeridians(np.arange(-180,180,20),color='0.7')
 m.drawmapboundary()
 
 # blue marble background (pretty, but slow).
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2008年12月31日 18:49:12
Revision: 6724
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6724&view=rev
Author: jswhit
Date: 2008年12月31日 18:49:07 +0000 (2008年12月31日)
Log Message:
-----------
fix bluemarble for full-disk aeqd, update garp.py example.
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/garp.py
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
Modified: trunk/toolkits/basemap/examples/garp.py
===================================================================
--- trunk/toolkits/basemap/examples/garp.py	2008年12月31日 17:10:51 UTC (rev 6723)
+++ trunk/toolkits/basemap/examples/garp.py	2008年12月31日 18:49:07 UTC (rev 6724)
@@ -17,17 +17,38 @@
 location = raw_input('name of location:')
 
 m = Basemap(resolution='c',projection='aeqd',lat_0=lat_0,lon_0=lon_0)
-# fill background.
-m.drawmapboundary(fill_color='aqua')
-# draw coasts and fill continents.
-m.drawcoastlines(linewidth=0.5)
-m.fillcontinents(color='coral',lake_color='aqua')
-# 20 degree graticule.
+
+# draw coastlines and fill continents.
+# **it's easy to make this fail with global aeqd plots.
+# For example, if the center point is at the North Pole,
+# the continent filling routines get confused and fills
+# the outside of Antartica instead of the inside**
+
+#m.drawmapboundary(fill_color='white')
+#m.drawcoastlines(linewidth=0.5)
+#m.fillcontinents(color='black',lake_color='white')
+#m.drawparallels(np.arange(-80,81,20))
+#m.drawmeridians(np.arange(-180,180,20))
+
+# draw lsmask instead of drawing continents (slower, but more robust).
+
+m.drawlsmask(land_color='black',ocean_color='white',lakes=True)
 m.drawparallels(np.arange(-80,81,20))
 m.drawmeridians(np.arange(-180,180,20))
-# draw a black dot at the center.
+m.drawmapboundary()
+
+# blue marble background (pretty, but slow).
+
+#m.bluemarble(scale=0.5)
+#m.drawparallels(np.arange(-80,81,20),color='0.5')
+#m.drawmeridians(np.arange(-180,180,20),color='0.5')
+#m.drawmapboundary(color='0.5')
+
+# draw a red dot at the center.
 xpt, ypt = m(lon_0, lat_0)
-m.plot([xpt],[ypt],'ko') 
+m.plot([xpt],[ypt],'ro') 
+
 # draw the title.
 plt.title('The World According to Garp in '+location)
+
 plt.show()
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 17:10:51 UTC (rev 6723)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 18:49:07 UTC (rev 6724)
@@ -3317,7 +3317,8 @@
 self.transform_scalar(self._bm_rgba[:,:,k],\
 self._bm_lons,self._bm_lats,nx,ny,returnxy=True)
 # for ortho,geos mask pixels outside projection limb.
- if self.projection in ['geos','ortho']:
+ if self.projection in ['geos','ortho'] or \
+ (self.projection == 'aeqd' and self._fulldisk):
 lonsr,latsr = self(x,y,inverse=True)
 mask = ma.zeros((ny,nx,4),np.int8)
 mask[:,:,0] = np.logical_or(lonsr>1.e20,latsr>1.e30)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6723
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6723&view=rev
Author: jswhit
Date: 2008年12月31日 17:10:51 +0000 (2008年12月31日)
Log Message:
-----------
more comments added to document proj4 bug
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 17:00:34 UTC (rev 6722)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 17:10:51 UTC (rev 6723)
@@ -99,7 +99,11 @@
 # raise an exception for ellipsoids - there appears to be a bug
 # in proj4 that causes the inverse transform to fail for points
 # more than 90 degrees of arc away from center point for ellipsoids
- # (works fine for spheres)
+ # (works fine for spheres) - below is an example
+ #from pyproj import Proj
+ #p1 = Proj(proj='aeqd',a=6378137.00,b=6356752.3142,lat_0=0,lon_0=0)
+ #x,y= p1(91,0)
+ #lon,lat = p1(x,y,inverse=True) # lon is 89 instead of 91
 if self.ellipsoid:
 msg = dedent("""
 full disk (whole world) Azimuthal Equidistant projection can
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6722
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6722&view=rev
Author: jswhit
Date: 2008年12月31日 17:00:34 +0000 (2008年12月31日)
Log Message:
-----------
add some comments
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 16:29:37 UTC (rev 6721)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 17:00:34 UTC (rev 6722)
@@ -96,13 +96,17 @@
 urcrnrlat == 90):
 self._fulldisk = True
 self._proj4 = pyproj.Proj(projparams)
+ # raise an exception for ellipsoids - there appears to be a bug
+ # in proj4 that causes the inverse transform to fail for points
+ # more than 90 degrees of arc away from center point for ellipsoids
+ # (works fine for spheres)
 if self.ellipsoid:
 msg = dedent("""
 full disk (whole world) Azimuthal Equidistant projection can
 only be drawn for a perfect sphere""")
 raise ValueError(msg)
- llcrnrx = -np.pi*self.rminor
- llcrnry = -np.pi*self.rminor
+ llcrnrx = -np.pi*self.rmajor
+ llcrnry = -np.pi*self.rmajor
 self._width = -llcrnrx
 self._height = -llcrnry
 urcrnrx = -llcrnrx
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6721
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6721&view=rev
Author: jswhit
Date: 2008年12月31日 16:29:37 +0000 (2008年12月31日)
Log Message:
-----------
fix typo
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 14:41:54 UTC (rev 6720)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 16:29:37 UTC (rev 6721)
@@ -101,8 +101,8 @@
 full disk (whole world) Azimuthal Equidistant projection can
 only be drawn for a perfect sphere""")
 raise ValueError(msg)
- llcrnrx = -0.5*(self.rmajor+self.rminor)
- llcrnry = -0.5*(self.rmajor+self.rminor)
+ llcrnrx = -np.pi*self.rminor
+ llcrnry = -np.pi*self.rminor
 self._width = -llcrnrx
 self._height = -llcrnry
 urcrnrx = -llcrnrx
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2008年12月31日 14:42:07
Revision: 6720
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6720&view=rev
Author: jswhit
Date: 2008年12月31日 14:41:54 +0000 (2008年12月31日)
Log Message:
-----------
fix bug in fulldisk aeqd, change garp.py example to plot whole disk
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/garp.py
Modified: trunk/toolkits/basemap/examples/garp.py
===================================================================
--- trunk/toolkits/basemap/examples/garp.py	2008年12月31日 14:37:44 UTC (rev 6719)
+++ trunk/toolkits/basemap/examples/garp.py	2008年12月31日 14:41:54 UTC (rev 6720)
@@ -11,20 +11,12 @@
 # it will be to reach that destination.
 # The specified point shows up as a red dot in the center of the map.
 
-# This example shows how to use the width and height keywords
-# to specify the map projection region (instead of specifying
-# the lat/lon of the upper right and lower left corners).
-
 # user enters the lon/lat of the point, and it's name
 lon_0 = float(raw_input('input reference lon (degrees):'))
 lat_0 = float(raw_input('input reference lat (degrees):'))
 location = raw_input('name of location:')
 
-# use these values to setup Basemap instance.
-width = 28000000
-m = Basemap(width=width,height=width,\
- resolution='c',projection='aeqd',\
- lat_0=lat_0,lon_0=lon_0)
+m = Basemap(resolution='c',projection='aeqd',lat_0=lat_0,lon_0=lon_0)
 # fill background.
 m.drawmapboundary(fill_color='aqua')
 # draw coasts and fill continents.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2008年12月31日 14:37:48
Revision: 6719
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6719&view=rev
Author: jswhit
Date: 2008年12月31日 14:37:44 +0000 (2008年12月31日)
Log Message:
-----------
whole world aeqd added
Modified Paths:
--------------
 trunk/toolkits/basemap/Changelog
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog	2008年12月31日 13:20:50 UTC (rev 6718)
+++ trunk/toolkits/basemap/Changelog	2008年12月31日 14:37:44 UTC (rev 6719)
@@ -1,4 +1,7 @@
 version 0.99.3 (not yet released)
+ * if upper right/lower left corners nor width/height given for
+ azimuthal equidistant ('aeqd') the whole world is drawn in 
+ a circle (only works for perfect spheres, not ellipsoids).
 * have setup.py check for already installed pyshapelib (just
 like it does for httplib2 and pydap).
 * Basemap will now look for it's data in BASEMAPDATA.
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 13:20:50 UTC (rev 6718)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/__init__.py	2008年12月31日 14:37:44 UTC (rev 6719)
@@ -625,10 +625,17 @@
 raise ValueError, 'must specify lat_0 and lon_0 for Azimuthal Equidistant basemap'
 if not using_corners:
 if width is None or height is None:
- raise ValueError, 'must either specify lat/lon values of corners (llcrnrlon,llcrnrlat,ucrnrlon,urcrnrlat) in degrees or width and height in meters'
+ self._fulldisk = True
+ llcrnrlon = -180.
+ llcrnrlat = -90.
+ urcrnrlon = 180
+ urcrnrlat = 90.
+ else:
+ self._fulldisk = False
 if lon_0 is None or lat_0 is None:
 raise ValueError, 'must specify lon_0 and lat_0 when using width, height to specify projection region'
- llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
+ if not self._fulldisk:
+ llcrnrlon,llcrnrlat,urcrnrlon,urcrnrlat = _choosecorners(width,height,**projparams)
 self.llcrnrlon = llcrnrlon; self.llcrnrlat = llcrnrlat
 self.urcrnrlon = urcrnrlon; self.urcrnrlat = urcrnrlat
 elif projection in _cylproj:
@@ -1046,12 +1053,8 @@
 if self.projection in ['ortho','geos']:
 # circular region.
 thetas = np.linspace(0.,2.*np.pi,2*nx*ny)[:-1]
- if self.projection == 'ortho':
- rminor = self.rmajor
- rmajor = self.rmajor
- else:
- rminor = self._height
- rmajor = self._width
+ rminor = self._height
+ rmajor = self._width
 x = rmajor*np.cos(thetas) + rmajor
 y = rminor*np.sin(thetas) + rminor
 b = np.empty((len(x),2),np.float64)
@@ -1075,6 +1078,16 @@
 projparms['x_0']=-llcrnrx
 projparms['y_0']=-llcrnry
 maptran = pyproj.Proj(projparms)
+ elif self.projection == 'aeqd' and self._fulldisk:
+ # circular region.
+ thetas = np.linspace(0.,2.*np.pi,2*nx*ny)[:-1]
+ rminor = self._height
+ rmajor = self._width
+ x = rmajor*np.cos(thetas) + rmajor
+ y = rminor*np.sin(thetas) + rminor
+ b = np.empty((len(x),2),np.float64)
+ b[:,0]=x; b[:,1]=y
+ boundaryxy = _geoslib.Polygon(b)
 elif self.projection in _pseudocyl:
 # quasi-elliptical region.
 lon_0 = self.projparams['lon_0']
@@ -1188,11 +1201,10 @@
 elif ax is None and self.ax is not None:
 ax = self.ax
 limb = None
- if self.projection == 'ortho':
- limb = Circle((self.rmajor,self.rmajor),self.rmajor)
- elif self.projection == 'geos':
+ if self.projection in ['ortho','geos'] or (self.projection=='aeqd' and\
+ self._fulldisk):
 limb = Ellipse((self._width,self._height),2.*self._width,2.*self._height)
- if self.projection in ['ortho','geos'] and self._fulldisk:
+ if self.projection in ['ortho','geos','aeqd'] and self._fulldisk:
 # elliptical region.
 ax.add_patch(limb)
 if fill_color is None:
@@ -1822,7 +1834,7 @@
 linecolls[circ] = (lines,[])
 # draw labels for parallels
 # parallels not labelled for fulldisk orthographic or geostationary
- if self.projection in ['ortho','geos','vandg'] and max(labels):
+ if self.projection in ['ortho','geos','vandg','aeqd'] and max(labels):
 if self.projection == 'vandg' or self._fulldisk:
 print 'Warning: Cannot label parallels on %s basemap' % _projnames[self.projection]
 labels = [0,0,0,0]
@@ -2068,9 +2080,12 @@
 if self.projection in ['sinu','moll','vandg'] and max(labels):
 print 'Warning: Cannot label meridians on %s basemap' % _projnames[self.projection]
 labels = [0,0,0,0]
- if self.projection in ['ortho','geos'] and max(labels):
+ if self.projection in ['ortho','geos','aeqd'] and max(labels):
 if self._fulldisk:
- print 'Warning: Cannot label meridians on full-disk Geostationary or Orthographic basemap'
+ print dedent(
+ """'Warning: Cannot label meridians on full-disk
+ Geostationary, Orthographic or Azimuthal equidistant basemap
+ """)
 labels = [0,0,0,0]
 # search along edges of map to see if parallels intersect.
 # if so, find x,y location of intersection and draw a label there.
@@ -2535,7 +2550,7 @@
 # turn off axes frame for non-rectangular projections.
 if self.projection in _pseudocyl:
 ax.set_frame_on(False)
- if self.projection in ['ortho','geos'] and self._fulldisk:
+ if self.projection in ['ortho','geos','aeqd'] and self._fulldisk:
 ax.set_frame_on(False)
 # make sure aspect ratio of map preserved.
 # plot is re-centered in bounding rectangle.
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 13:20:50 UTC (rev 6718)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月31日 14:37:44 UTC (rev 6719)
@@ -1,6 +1,7 @@
 import numpy as np
 import pyproj
 import math
+from matplotlib.cbook import dedent
 
 __version__ = '1.2.2'
 _dg2rad = math.radians(1.)
@@ -70,19 +71,18 @@
 self.esq = (self.rmajor**2 - self.rminor**2)/self.rmajor**2
 self.llcrnrlon = llcrnrlon
 self.llcrnrlat = llcrnrlat
- if self.projection not in ['ortho','geos','cyl'] + _pseudocyl:
- self._proj4 = pyproj.Proj(projparams)
- llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat)
- elif self.projection == 'cyl':
+ if self.projection == 'cyl':
 llcrnrx = llcrnrlon
 llcrnry = llcrnrlat
- elif self.projection == 'ortho':
+ elif self.projection in 'ortho':
 if (llcrnrlon == -180 and llcrnrlat == -90 and
 urcrnrlon == 180 and urcrnrlat == 90):
 self._fulldisk = True
 self._proj4 = pyproj.Proj(projparams)
 llcrnrx = -self.rmajor
 llcrnry = -self.rmajor
+ self._width = 0.5*(self.rmajor+self.rminor)
+ self._height = 0.5*(self.rmajor+self.rminor)
 urcrnrx = -llcrnrx
 urcrnry = -llcrnry
 else:
@@ -91,6 +91,22 @@
 llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat)
 if llcrnrx > 1.e20 or llcrnry > 1.e20:
 raise ValueError(_lower_left_out_of_bounds)
+ elif self.projection == 'aeqd' and\
+ (llcrnrlon == -180 and llcrnrlat == -90 and urcrnrlon == 180 and\
+ urcrnrlat == 90):
+ self._fulldisk = True
+ self._proj4 = pyproj.Proj(projparams)
+ if self.ellipsoid:
+ msg = dedent("""
+ full disk (whole world) Azimuthal Equidistant projection can
+ only be drawn for a perfect sphere""")
+ raise ValueError(msg)
+ llcrnrx = -0.5*(self.rmajor+self.rminor)
+ llcrnry = -0.5*(self.rmajor+self.rminor)
+ self._width = -llcrnrx
+ self._height = -llcrnry
+ urcrnrx = -llcrnrx
+ urcrnry = -llcrnry
 elif self.projection == 'geos':
 self._proj4 = pyproj.Proj(projparams)
 # find major and minor axes of ellipse defining map proj region.
@@ -129,6 +145,10 @@
 urcrnrx,xtmp = self(projparams['lon_0']+180.,0)
 llcrnrx = -urcrnrx
 llcrnry = -urcrnry
+ else:
+ self._proj4 = pyproj.Proj(projparams)
+ llcrnrx, llcrnry = self(llcrnrlon,llcrnrlat)
+ if self.projection == 'aeqd': self._fulldisk=False
 # compute x_0, y_0 so ll corner of domain is x=0,y=0.
 # note that for 'cyl' x,y == lon,lat
 self.projparams['x_0']=-llcrnrx
@@ -144,18 +164,10 @@
 if urcrnrislatlon:
 self.urcrnrlon = urcrnrlon
 self.urcrnrlat = urcrnrlat
- if self.projection not in ['ortho','geos'] + _pseudocyl:
+ if self.projection not in ['ortho','geos','aeqd'] + _pseudocyl:
 urcrnrx,urcrnry = self(urcrnrlon,urcrnrlat)
- elif self.projection == 'ortho':
+ elif self.projection in ['ortho','geos','aeqd']:
 if self._fulldisk:
- urcrnrx = 2.*self.rmajor
- urcrnry = 2.*self.rmajor
- else:
- urcrnrx,urcrnry = self(urcrnrlon,urcrnrlat)
- if urcrnrx > 1.e20 or urcrnry > 1.e20:
- raise ValueError(_upper_right_out_of_bounds)
- elif self.projection == 'geos':
- if self._fulldisk:
 urcrnrx = 2.*self._width
 urcrnry = 2.*self._height
 else:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jo...@us...> - 2008年12月31日 13:20:56
Revision: 6718
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6718&view=rev
Author: jouni
Date: 2008年12月31日 13:20:50 +0000 (2008年12月31日)
Log Message:
-----------
Improve pdf usetex by adding support for font effects
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/doc/api/index_backend_api.rst
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
 trunk/matplotlib/lib/matplotlib/dviread.py
 trunk/matplotlib/lib/matplotlib/type1font.py
Added Paths:
-----------
 trunk/matplotlib/doc/api/dviread.rst
 trunk/matplotlib/doc/api/type1font.rst
 trunk/matplotlib/examples/pylab_examples/usetex_fonteffects.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2008年12月30日 16:06:59 UTC (rev 6717)
+++ trunk/matplotlib/CHANGELOG	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -1,3 +1,6 @@
+2008年12月31日 Improve pdf usetex by adding support for font effects
+ (slanting and extending). - JKS
+
 2008年12月29日 Fix a bug in pdf usetex support, which occurred if the same
 Type-1 font was used with different encodings, e.g. with
 Minion Pro and MnSymbol. - JKS
Added: trunk/matplotlib/doc/api/dviread.rst
===================================================================
--- trunk/matplotlib/doc/api/dviread.rst	 (rev 0)
+++ trunk/matplotlib/doc/api/dviread.rst	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -0,0 +1,8 @@
+
+:mod:`matplotlib.dviread`
+=========================
+
+.. automodule:: matplotlib.dviread
+ :members:
+ :undoc-members:
+ :show-inheritance:
Modified: trunk/matplotlib/doc/api/index_backend_api.rst
===================================================================
--- trunk/matplotlib/doc/api/index_backend_api.rst	2008年12月30日 16:06:59 UTC (rev 6717)
+++ trunk/matplotlib/doc/api/index_backend_api.rst	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -8,3 +8,5 @@
 backend_gtkagg_api.rst
 backend_qt4agg_api.rst
 backend_wxagg_api.rst
+ dviread.rst
+ type1font.rst
Added: trunk/matplotlib/doc/api/type1font.rst
===================================================================
--- trunk/matplotlib/doc/api/type1font.rst	 (rev 0)
+++ trunk/matplotlib/doc/api/type1font.rst	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -0,0 +1,8 @@
+
+:mod:`matplotlib.type1font`
+===========================
+
+.. automodule:: matplotlib.type1font
+ :members:
+ :undoc-members:
+ :show-inheritance:
Added: trunk/matplotlib/examples/pylab_examples/usetex_fonteffects.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/usetex_fonteffects.py	 (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/usetex_fonteffects.py	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -0,0 +1,22 @@
+# This script demonstrates that font effects specified in your pdftex.map
+# are now supported in pdf usetex.
+
+import matplotlib
+matplotlib.rc('text', usetex=True)
+import pylab
+
+def setfont(font):
+ return r'\font\a %s at 14pt\a ' % font
+
+for y, font, text in zip(range(5),
+ ['ptmr8r', 'ptmri8r', 'ptmro8r', 'ptmr8rn', 'ptmrr8re'],
+ ['Nimbus Roman No9 L ' + x for x in
+ ['', 'Italics (real italics for comparison)',
+ '(slanted)', '(condensed)', '(extended)']]):
+ pylab.text(0, y, setfont(font) + text)
+
+pylab.ylim(-1, 5)
+pylab.xlim(-0.2, 0.6)
+pylab.setp(pylab.gca(), frame_on=False, xticks=(), yticks=())
+pylab.title('Usetex font effects')
+pylab.savefig('usetex_fonteffects.pdf')
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月30日 16:06:59 UTC (rev 6717)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -500,7 +500,7 @@
 # from pdf.use14corefonts
 fontdictObject = self._write_afm_font(filename)
 elif self.dviFontInfo.has_key(filename):
- # a Type 1 font from a dvi file
+ # a Type 1 font from a dvi file; the filename is really the TeX name
 fontdictObject = self.embedType1(filename, self.dviFontInfo[filename])
 else:
 # a normal TrueType font
@@ -525,22 +525,25 @@
 return fontdictObject
 
 def embedType1(self, texname, fontinfo):
- # TODO: font effects such as SlantFont
 matplotlib.verbose.report(
- 'Embedding Type 1 font ' + fontinfo.fontfile +
- ' with encoding ' + (fontinfo.encodingfile or '(none)'),
+ 'Embedding ' + texname +
+ ' which is the Type 1 font ' + fontinfo.fontfile +
+ ' with encoding ' + (fontinfo.encodingfile or '(none)') +
+ ' and effects ' + `fontinfo.effects`,
 'debug')
 
- # Use FT2Font to get several font properties
- font = FT2Font(fontinfo.fontfile)
+ t1font = type1font.Type1Font(fontinfo.fontfile)
+ if fontinfo.effects:
+ t1font = t1font.transform(fontinfo.effects)
 
 # Font descriptors may be shared between differently encoded
 # Type-1 fonts, so only create a new descriptor if there is no
 # existing descriptor for this font.
- fontdesc = self.type1Descriptors.get(fontinfo.fontfile)
+ effects = (fontinfo.effects.get('slant', 0.0), fontinfo.effects.get('extend', 1.0))
+ fontdesc = self.type1Descriptors.get((fontinfo.fontfile, effects))
 if fontdesc is None:
- fontdesc = self.createType1Descriptor(font, fontinfo.fontfile)
- self.type1Descriptors[fontinfo.fontfile] = fontdesc
+ fontdesc = self.createType1Descriptor(t1font, fontinfo.fontfile)
+ self.type1Descriptors[(fontinfo.fontfile, effects)] = fontdesc
 
 # Widths
 widthsObject = self.reserveObject('font widths')
@@ -551,7 +554,7 @@
 fontdict = {
 'Type': Name('Font'),
 'Subtype': Name('Type1'),
- 'BaseFont': Name(font.postscript_name),
+ 'BaseFont': Name(t1font.prop['FontName']),
 'FirstChar': 0,
 'LastChar': len(fontinfo.widths) - 1,
 'Widths': widthsObject,
@@ -571,14 +574,14 @@
 self.writeObject(fontdictObject, fontdict)
 return fontdictObject
 
- def createType1Descriptor(self, font, fontfile):
+ def createType1Descriptor(self, t1font, fontfile):
 # Create and write the font descriptor and the font file
 # of a Type-1 font
 fontdescObject = self.reserveObject('font descriptor')
 fontfileObject = self.reserveObject('font file')
 
- _, _, fullname, familyname, weight, italic_angle, fixed_pitch, \
- ul_position, ul_thickness = font.get_ps_font_info()
+ italic_angle = t1font.prop['ItalicAngle']
+ fixed_pitch = t1font.prop['isFixedPitch']
 
 flags = 0
 if fixed_pitch: flags |= 1 << 0 # fixed width
@@ -590,18 +593,20 @@
 if 0: flags |= 1 << 17 # TODO: small caps
 if 0: flags |= 1 << 18 # TODO: force bold
 
+ ft2font = FT2Font(fontfile)
+ 
 descriptor = {
 'Type': Name('FontDescriptor'),
- 'FontName': Name(font.postscript_name),
+ 'FontName': Name(t1font.prop['FontName']),
 'Flags': flags,
- 'FontBBox': font.bbox,
+ 'FontBBox': ft2font.bbox,
 'ItalicAngle': italic_angle,
- 'Ascent': font.ascender,
- 'Descent': font.descender,
+ 'Ascent': ft2font.ascender,
+ 'Descent': ft2font.descender,
 'CapHeight': 1000, # TODO: find this out
 'XHeight': 500, # TODO: this one too
 'FontFile': fontfileObject,
- 'FontFamily': familyname,
+ 'FontFamily': t1font.prop['FamilyName'],
 'StemV': 50, # TODO
 # (see also revision 3874; but not all TeX distros have AFM files!)
 #'FontWeight': a number where 400 = Regular, 700 = Bold
@@ -609,7 +614,6 @@
 
 self.writeObject(fontdescObject, descriptor)
 
- t1font = type1font.Type1Font(fontfile)
 self.beginStream(fontfileObject.id, None,
 { 'Length1': len(t1font.parts[0]),
 'Length2': len(t1font.parts[1]),
@@ -1369,14 +1373,14 @@
 self.file.dviFontInfo[dvifont.texname] = Bunch(
 fontfile=psfont.filename,
 encodingfile=psfont.encoding,
+ effects=psfont.effects,
 widths=dvifont.widths,
 dvifont=dvifont)
- # TODO: font effects
 seq += [['font', pdfname, dvifont.size]]
 oldfont = dvifont
 seq += [['text', x1, y1, [chr(glyph)], x1+width]]
 
- # Find consecutive text strings with constant x coordinate and
+ # Find consecutive text strings with constant y coordinate and
 # combine into a sequence of strings and kerns, or just one
 # string (if any kerns would be less than 0.1 points).
 i, curx = 0, 0
Modified: trunk/matplotlib/lib/matplotlib/dviread.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/dviread.py	2008年12月30日 16:06:59 UTC (rev 6717)
+++ trunk/matplotlib/lib/matplotlib/dviread.py	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -1,12 +1,14 @@
 """
 An experimental module for reading dvi files output by TeX. Several
 limitations make this not (currently) useful as a general-purpose dvi
-preprocessor.
+preprocessor, but it is currently used by the pdf backend for
+processing usetex text.
 
 Interface::
 
 dvi = Dvi(filename, 72)
- for page in dvi: # iterate over pages
+ # iterate over pages (but only one page is supported for now):
+ for page in dvi:
 w, h, d = page.width, page.height, page.descent
 for x,y,font,glyph,width in page.text:
 fontname = font.texname
@@ -49,7 +51,7 @@
 """
 Iterate through the pages of the file.
 
- Returns (text, pages) pairs, where:
+ Returns (text, boxes) pairs, where:
 text is a list of (x, y, fontnum, glyphnum, width) tuples
 boxes is a list of (x, y, height, width) tuples
 
@@ -131,8 +133,8 @@
 
 def _arg(self, nbytes, signed=False):
 """
- Read and return an integer argument "nbytes" long.
- Signedness is determined by the "signed" keyword.
+ Read and return an integer argument *nbytes* long.
+ Signedness is determined by the *signed* keyword.
 """
 str = self.file.read(nbytes)
 value = ord(str[0])
@@ -144,7 +146,7 @@
 
 def _dispatch(self, byte):
 """
- Based on the opcode "byte", read the correct kinds of
+ Based on the opcode *byte*, read the correct kinds of
 arguments from the dvi file and call the method implementing
 that opcode with those arguments.
 """
@@ -385,9 +387,27 @@
 Object that holds a font's texname and size, supports comparison,
 and knows the widths of glyphs in the same units as the AFM file.
 There are also internal attributes (for use by dviread.py) that
- are _not_ used for comparison.
+ are *not* used for comparison.
 
 The size is in Adobe points (converted from TeX points).
+
+ .. attribute:: texname
+ 
+ Name of the font as used internally by TeX and friends. This
+ is usually very different from any external font names, and
+ :class:`dviread.PsfontsMap` can be used to find the external
+ name of the font.
+
+ .. attribute:: size
+ 
+ Size of the font in Adobe points, converted from the slightly
+ smaller TeX points.
+
+ .. attribute:: widths
+ 
+ Widths of glyphs in glyph-space units, typically 1/1000ths of
+ the point size.
+ 
 """
 __slots__ = ('texname', 'size', 'widths', '_scale', '_vf', '_tfm')
 
@@ -532,17 +552,27 @@
 A TeX Font Metric file. This implementation covers only the bare
 minimum needed by the Dvi class.
 
- Attributes:
+ .. attribute:: checksum
 
- checksum: for verifying against dvi file
+ Used for verifying against the dvi file.
 
- design_size: design size of the font (in what units?)
+ .. attribute:: design_size
 
- width[i]: width of character \#i, needs to be scaled
- by the factor specified in the dvi file
- (this is a dict because indexing may not start from 0)
+ Design size of the font (in what units?)
 
- height[i], depth[i]: height and depth of character \#i
+ .. attribute:: width
+
+ Width of each character, needs to be scaled by the factor
+ specified in the dvi file. This is a dict because indexing may
+ not start from 0.
+
+ .. attribute:: height
+
+ Height of each character.
+ 
+ .. attribute:: depth
+ 
+ Depth of each character.
 """
 __slots__ = ('checksum', 'design_size', 'width', 'height', 'depth')
 
@@ -581,8 +611,20 @@
 class PsfontsMap(object):
 """
 A psfonts.map formatted file, mapping TeX fonts to PS fonts.
- Usage: map = PsfontsMap('.../psfonts.map'); map['cmr10']
+ Usage::
 
+ >>> map = PsfontsMap(find_tex_file('pdftex.map'))
+ >>> entry = map['ptmbo8r']
+ >>> entry.texname
+ 'ptmbo8r'
+ >>> entry.psname
+ 'Times-Bold'
+ >>> entry.encoding
+ '/usr/local/texlive/2008/texmf-dist/fonts/enc/dvips/base/8r.enc'
+ >>> entry.effects
+ {'slant': 0.16700000000000001}
+ >>> entry.filename
+
 For historical reasons, TeX knows many Type-1 fonts by different
 names than the outside world. (For one thing, the names have to
 fit in eight characters.) Also, TeX's native fonts are not Type-1
@@ -594,11 +636,12 @@
 file names.
 
 A texmf tree typically includes mapping files called e.g.
- psfonts.map, pdftex.map, dvipdfm.map. psfonts.map is used by
+ psfonts.map, pdftex.map, dvipdfm.map. psfonts.map is used by
 dvips, pdftex.map by pdfTeX, and dvipdfm.map by dvipdfm.
- psfonts.map might avoid embedding the 35 PostScript fonts, while
- the pdf-related files perhaps only avoid the "Base 14" pdf fonts.
- But the user may have configured these files differently.
+ psfonts.map might avoid embedding the 35 PostScript fonts (i.e.,
+ have no filename for them, as in the Times-Bold example above),
+ while the pdf-related files perhaps only avoid the "Base 14" pdf
+ fonts. But the user may have configured these files differently.
 """
 __slots__ = ('_font',)
 
@@ -655,10 +698,10 @@
 subsetting, but I have no example of << in my TeX installation.
 """
 texname, psname = words[:2]
- effects, encoding, filename = [], None, None
+ effects, encoding, filename = '', None, None
 for word in words[2:]:
 if not word.startswith('<'):
- effects.append(word)
+ effects = word
 else:
 word = word.lstrip('<')
 if word.startswith('['):
@@ -670,6 +713,18 @@
 else:
 assert filename is None
 filename = word
+
+ eff = effects.split()
+ effects = {}
+ try:
+ effects['slant'] = float(eff[eff.index('SlantFont')-1])
+ except ValueError:
+ pass
+ try:
+ effects['extend'] = float(eff[eff.index('ExtendFont')-1])
+ except ValueError:
+ pass
+
 self._font[texname] = mpl_cbook.Bunch(
 texname=texname, psname=psname, effects=effects,
 encoding=encoding, filename=filename)
@@ -733,13 +788,18 @@
 
 def find_tex_file(filename, format=None):
 """
- Call kpsewhich to find a file in the texmf tree.
- If format is not None, it is used as the value for the --format option.
- See the kpathsea documentation for more information.
+ Call :program:`kpsewhich` to find a file in the texmf tree. If
+ *format* is not None, it is used as the value for the
+ :option:`--format` option.
 
 Apparently most existing TeX distributions on Unix-like systems
 use kpathsea. I hear MikTeX (a popular distribution on Windows)
 doesn't use kpathsea, so what do we do? (TODO)
+
+ .. seealso::
+
+ `Kpathsea documentation <http://www.tug.org/kpathsea/>`_
+ The library that :program:`kpsewhich` is part of.
 """
 
 cmd = ['kpsewhich']
Modified: trunk/matplotlib/lib/matplotlib/type1font.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/type1font.py	2008年12月30日 16:06:59 UTC (rev 6717)
+++ trunk/matplotlib/lib/matplotlib/type1font.py	2008年12月31日 13:20:50 UTC (rev 6718)
@@ -1,37 +1,70 @@
 """
-A class representing a Type 1 font.
+This module contains a class representing a Type 1 font.
 
-This version merely reads pfa and pfb files and splits them for
-embedding in pdf files. There is no support yet for subsetting or
-anything like that.
+This version reads pfa and pfb files and splits them for embedding in
+pdf files. It also supports SlantFont and ExtendFont transformations,
+similarly to pdfTeX and friends. There is no support yet for
+subsetting.
 
-Usage (subject to change):
+Usage::
 
- font = Type1Font(filename)
- clear_part, encrypted_part, finale = font.parts
+ >>> font = Type1Font(filename)
+ >>> clear_part, encrypted_part, finale = font.parts
+ >>> slanted_font = font.transform({'slant': 0.167})
+ >>> extended_font = font.transform({'extend': 1.2})
 
-Source: Adobe Technical Note #5040, Supporting Downloadable PostScript
-Language Fonts.
+Sources:
 
-If extending this class, see also: Adobe Type 1 Font Format, Adobe
-Systems Incorporated, third printing, v1.1, 1993. ISBN 0-201-57044-0.
+* Adobe Technical Note #5040, Supporting Downloadable PostScript
+ Language Fonts.
+
+* Adobe Type 1 Font Format, Adobe Systems Incorporated, third printing,
+ v1.1, 1993. ISBN 0-201-57044-0.
 """
 
+import matplotlib.cbook as cbook
+import cStringIO
+import itertools
+import numpy as np
 import re
 import struct
 
 class Type1Font(object):
+ """
+ A class representing a Type-1 font, for use by backends.
 
- def __init__(self, filename):
- file = open(filename, 'rb')
- try:
- data = self._read(file)
- finally:
- file.close()
- self.parts = self._split(data)
- #self._parse()
+ .. attribute:: parts
 
+ A 3-tuple of the cleartext part, the encrypted part, and the
+ finale of zeros.
+
+ .. attribute:: prop
+
+ A dictionary of font properties.
+ """
+ __slots__ = ('parts', 'prop')
+
+ def __init__(self, input):
+ """
+ Initialize a Type-1 font. *input* can be either the file name of
+ a pfb file or a 3-tuple of already-decoded Type-1 font parts.
+ """
+ if isinstance(input, tuple) and len(input) == 3:
+ self.parts = input
+ else:
+ file = open(input, 'rb')
+ try:
+ data = self._read(file)
+ finally:
+ file.close()
+ self.parts = self._split(data)
+ 
+ self._parse()
+
 def _read(self, file):
+ """
+ Read the font from a file, decoding into usable parts.
+ """
 rawdata = file.read()
 if not rawdata.startswith(chr(128)):
 return rawdata
@@ -100,85 +133,177 @@
 return data[:len1], binary, data[idx:]
 
 _whitespace = re.compile(r'[0円\t\r014円\n ]+')
- _delim = re.compile(r'[()<>[]{}/%]')
 _token = re.compile(r'/{0,2}[^]0円\t\r\v\n ()<>{}/%[]+')
 _comment = re.compile(r'%[^\r\n\v]*')
 _instring = re.compile(r'[()\\]')
- def _parse(self):
+ @classmethod
+ def _tokens(cls, text):
 """
- A very limited kind of parsing to find the Encoding of the
- font.
+ A PostScript tokenizer. Yield (token, value) pairs such as
+ ('whitespace', ' ') or ('name', '/Foobar').
 """
- def tokens(text):
- """
- Yield pairs (position, token), ignoring comments and
- whitespace. Numbers count as tokens.
- """
- pos = 0
- while pos < len(text):
- match = self._comment.match(text[pos:]) or self._whitespace.match(text[pos:])
+ pos = 0
+ while pos < len(text):
+ match = cls._comment.match(text[pos:]) or cls._whitespace.match(text[pos:])
+ if match:
+ yield ('whitespace', match.group())
+ pos += match.end()
+ elif text[pos] == '(':
+ start = pos
+ pos += 1
+ depth = 1
+ while depth:
+ match = cls._instring.search(text[pos:])
+ if match is None: return
+ pos += match.end()
+ if match.group() == '(':
+ depth += 1
+ elif match.group() == ')':
+ depth -= 1
+ else: # a backslash - skip the next character
+ pos += 1
+ yield ('string', text[start:pos])
+ elif text[pos:pos+2] in ('<<', '>>'):
+ yield ('delimiter', text[pos:pos+2])
+ pos += 2
+ elif text[pos] == '<':
+ start = pos
+ pos += text[pos:].index('>')
+ yield ('string', text[start:pos])
+ else:
+ match = cls._token.match(text[pos:])
 if match:
+ try:
+ float(match.group())
+ yield ('number', match.group())
+ except ValueError:
+ yield ('name', match.group())
 pos += match.end()
- elif text[pos] == '(':
- start = pos
+ else:
+ yield ('delimiter', text[pos])
 pos += 1
- depth = 1
- while depth:
- match = self._instring.search(text[pos:])
- if match is None: return
- if match.group() == '(':
- depth += 1
- pos += 1
- elif match.group() == ')':
- depth -= 1
- pos += 1
- else:
- pos += 2
- yield (start, text[start:pos])
- elif text[pos:pos+2] in ('<<', '>>'):
- yield (pos, text[pos:pos+2])
- pos += 2
- elif text[pos] == '<':
- start = pos
- pos += text[pos:].index('>')
- yield (start, text[start:pos])
- else:
- match = self._token.match(text[pos:])
- if match:
- yield (pos, match.group())
- pos += match.end()
+
+ def _parse(self):
+ """
+ Find the values of various font properties. This limited kind
+ of parsing is described in Chapter 10 "Adobe Type Manager
+ Compatibility" of the Type-1 spec.
+ """
+ # Start with reasonable defaults
+ prop = { 'weight': 'Regular', 'ItalicAngle': 0.0, 'isFixedPitch': False,
+ 'UnderlinePosition': -100, 'UnderlineThickness': 50 }
+ tokenizer = self._tokens(self.parts[0])
+ filtered = itertools.ifilter(lambda x: x[0] != 'whitespace', tokenizer)
+ for token, value in filtered:
+ if token == 'name' and value.startswith('/'):
+ key = value[1:]
+ token, value = filtered.next()
+ if token == 'name':
+ if value in ('true', 'false'):
+ value = value == 'true'
 else:
- yield (pos, text[pos])
- pos += 1
+ value = value.lstrip('/')
+ elif token == 'string':
+ value = value.lstrip('(').rstrip(')')
+ elif token == 'number':
+ if '.' in value: value = float(value)
+ else: value = int(value)
+ else: # more complicated value such as an array
+ value = None
+ if key != 'FontInfo' and value is not None:
+ prop[key] = value
 
- enc_starts, enc_ends = None, None
- state = 0
- # State transitions:
- # 0 -> /Encoding -> 1
- # 1 -> StandardEncoding -> 2 -> def -> (ends)
- # 1 -> dup -> 4 -> put -> 5
- # 5 -> dup -> 4 -> put -> 5
- # 5 -> def -> (ends)
- for pos,token in tokens(self.parts[0]):
- if state == 0 and token == '/Encoding':
- enc_starts = pos
- state = 1
- elif state == 1 and token == 'StandardEncoding':
- state = 2
- elif state in (2,5) and token == 'def':
- enc_ends = pos+3
- break
- elif state in (1,5) and token == 'dup':
- state = 4
- elif state == 4 and token == 'put':
- state = 5
- self.enc_starts, self.enc_ends = enc_starts, enc_ends
+ # Fill in the various *Name properties
+ if not prop.has_key('FontName'):
+ prop['FontName'] = prop.get('FullName') or prop.get('FamilyName') or 'Unknown'
+ if not prop.has_key('FullName'):
+ prop['FullName'] = prop['FontName']
+ if not prop.has_key('FamilyName'):
+ extras = r'(?i)([ -](regular|plain|italic|oblique|(semi)?bold|(ultra)?light|extra|condensed))+$'
+ prop['FamilyName'] = re.sub(extras, '', prop['FullName'])
 
+ self.prop = prop
+ 
+ @classmethod
+ def _transformer(cls, tokens, slant, extend):
+ def fontname(name):
+ result = name
+ if slant: result += '_Slant_' + str(int(1000*slant))
+ if extend != 1.0: result += '_Extend_' + str(int(1000*extend))
+ return result
+
+ def italicangle(angle):
+ return str(float(angle) - np.arctan(slant)/np.pi*180)
+
+ def fontmatrix(array):
+ array = array.lstrip('[').rstrip(']').strip().split()
+ array = [ float(x) for x in array ]
+ oldmatrix = np.eye(3,3)
+ oldmatrix[0:3,0] = array[::2]
+ oldmatrix[0:3,1] = array[1::2]
+ modifier = np.array([[extend, 0, 0],
+ [slant, 1, 0],
+ [0, 0, 1]])
+ newmatrix = np.dot(modifier, oldmatrix)
+ array[::2] = newmatrix[0:3,0]
+ array[1::2] = newmatrix[0:3,1]
+ return '[' + ' '.join(str(x) for x in array) + ']'
+
+ def replace(fun):
+ def replacer(tokens):
+ token, value = tokens.next() # name, e.g. /FontMatrix
+ yield value
+ token, value = tokens.next() # possible whitespace
+ while token == 'whitespace':
+ yield value
+ token, value = tokens.next()
+ if value != '[': # name/number/etc.
+ yield fun(value)
+ else: # array, e.g. [1 2 3]
+ array = []
+ while value != ']':
+ array += value
+ token, value = tokens.next()
+ array += value
+ yield fun(''.join(array))
+ return replacer
+
+ def suppress(tokens):
+ for x in itertools.takewhile(lambda x: x[1] != 'def', tokens):
+ pass
+ yield ''
+ 
+ table = { '/FontName': replace(fontname),
+ '/ItalicAngle': replace(italicangle),
+ '/FontMatrix': replace(fontmatrix),
+ '/UniqueID': suppress }
+
+ while True:
+ token, value = tokens.next()
+ if token == 'name' and value in table:
+ for value in table[value](itertools.chain([(token, value)], tokens)):
+ yield value
+ else:
+ yield value
+ 
+ def transform(self, effects):
+ """
+ Transform the font by slanting or extending. *effects* should
+ be a dict where ``effects['slant']`` is the tangent of the
+ angle that the font is to be slanted to the right (so negative
+ values slant to the left) and ``effects['extend']`` is the
+ multiplier by which the font is to be extended (so values less
+ than 1.0 condense). Returns a new :class:`Type1Font` object.
+ """
+
+ buffer = cStringIO.StringIO()
+ tokenizer = self._tokens(self.parts[0])
+ for value in self._transformer(tokenizer,
+ slant=effects.get('slant', 0.0),
+ extend=effects.get('extend', 1.0)):
+ buffer.write(value)
+ result = buffer.getvalue()
+ buffer.close()
+
+ return Type1Font((result, self.parts[1], self.parts[2]))
 
-if __name__ == '__main__':
- import sys
- font = Type1Font(sys.argv[1])
- parts = font.parts
- print len(parts[0]), len(parts[1]), len(parts[2])
- #print parts[0][font.enc_starts:font.enc_ends]
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2008年12月30日 16:07:06
Revision: 6717
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6717&view=rev
Author: jdh2358
Date: 2008年12月30日 16:06:59 +0000 (2008年12月30日)
Log Message:
-----------
added rcparams import to path
Modified Paths:
--------------
 branches/v0_98_5_maint/lib/matplotlib/path.py
Modified: branches/v0_98_5_maint/lib/matplotlib/path.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月29日 15:34:30 UTC (rev 6716)
+++ branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月30日 16:06:59 UTC (rev 6717)
@@ -12,6 +12,7 @@
 point_in_path_collection, get_path_collection_extents, \
 path_in_path, path_intersects_path, convert_path_to_polygons
 from matplotlib.cbook import simple_linear_interpolation
+from matplotlib import rcParams
 
 class Path(object):
 """
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 15:34:33
Revision: 6716
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6716&view=rev
Author: mdboom
Date: 2008年12月29日 15:34:30 +0000 (2008年12月29日)
Log Message:
-----------
Merged revisions 6714-6715 via svnmerge from 
https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint
........
 r6714 | mdboom | 2008年12月29日 10:29:52 -0500 (2008年12月29日) | 2 lines
 
 Handle path.simplify rcParam in all backends.
........
 r6715 | mdboom | 2008年12月29日 10:33:18 -0500 (2008年12月29日) | 2 lines
 
 Handle path.simplify rcParam in all backends.
........
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/path.py
Property Changed:
----------------
 trunk/matplotlib/
 trunk/matplotlib/doc/pyplots/README
 trunk/matplotlib/doc/sphinxext/gen_gallery.py
 trunk/matplotlib/doc/sphinxext/gen_rst.py
Property changes on: trunk/matplotlib
___________________________________________________________________
Modified: svnmerge-integrated
 - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6689
 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6715
Modified: svn:mergeinfo
 - /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673
 + /branches/v0_91_maint:5753-5771
/branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715
Property changes on: trunk/matplotlib/doc/pyplots/README
___________________________________________________________________
Modified: svn:mergeinfo
 - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673
 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715
Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py
___________________________________________________________________
Modified: svn:mergeinfo
 - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673
 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715
Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py
___________________________________________________________________
Modified: svn:mergeinfo
 - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771
/branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715
Modified: trunk/matplotlib/lib/matplotlib/path.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 15:33:18 UTC (rev 6715)
+++ trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 15:34:30 UTC (rev 6716)
@@ -112,7 +112,7 @@
 
 self.should_simplify = (rcParams['path.simplify'] and
 (len(vertices) >= 128 and
- (codes is None or np.all(codes <= Path.LINETO))))
+ (codes is None or np.all(codes <= Path.LINETO))))
 self.has_nonfinite = not np.isfinite(vertices).all()
 self.codes = codes
 self.vertices = vertices
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 15:33:24
Revision: 6715
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6715&view=rev
Author: mdboom
Date: 2008年12月29日 15:33:18 +0000 (2008年12月29日)
Log Message:
-----------
Handle path.simplify rcParam in all backends.
Modified Paths:
--------------
 branches/v0_98_5_maint/lib/matplotlib/path.py
Modified: branches/v0_98_5_maint/lib/matplotlib/path.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月29日 15:29:52 UTC (rev 6714)
+++ branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月29日 15:33:18 UTC (rev 6715)
@@ -109,7 +109,7 @@
 assert vertices.ndim == 2
 assert vertices.shape[1] == 2
 
- self.should_simplify = (rcParam['path.simplify'] and
+ self.should_simplify = (rcParams['path.simplify'] and
 (len(vertices) >= 128 and
 (codes is None or np.all(codes <= Path.LINETO))))
 self.has_nonfinite = not np.isfinite(vertices).all()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 15:29:56
Revision: 6714
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6714&view=rev
Author: mdboom
Date: 2008年12月29日 15:29:52 +0000 (2008年12月29日)
Log Message:
-----------
Handle path.simplify rcParam in all backends.
Modified Paths:
--------------
 branches/v0_98_5_maint/lib/matplotlib/path.py
Modified: branches/v0_98_5_maint/lib/matplotlib/path.py
===================================================================
--- branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月29日 14:52:30 UTC (rev 6713)
+++ branches/v0_98_5_maint/lib/matplotlib/path.py	2008年12月29日 15:29:52 UTC (rev 6714)
@@ -109,8 +109,9 @@
 assert vertices.ndim == 2
 assert vertices.shape[1] == 2
 
- self.should_simplify = (len(vertices) >= 128 and
- (codes is None or np.all(codes <= Path.LINETO)))
+ self.should_simplify = (rcParam['path.simplify'] and
+ (len(vertices) >= 128 and
+ (codes is None or np.all(codes <= Path.LINETO))))
 self.has_nonfinite = not np.isfinite(vertices).all()
 self.codes = codes
 self.vertices = vertices
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jo...@us...> - 2008年12月29日 14:52:33
Revision: 6713
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6713&view=rev
Author: jouni
Date: 2008年12月29日 14:52:30 +0000 (2008年12月29日)
Log Message:
-----------
Fix buglet in path.py
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/path.py
Modified: trunk/matplotlib/lib/matplotlib/path.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 14:42:20 UTC (rev 6712)
+++ trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 14:52:30 UTC (rev 6713)
@@ -12,6 +12,7 @@
 point_in_path_collection, get_path_collection_extents, \
 path_in_path, path_intersects_path, convert_path_to_polygons
 from matplotlib.cbook import simple_linear_interpolation, maxdict
+from matplotlib import rcParams
 
 class Path(object):
 """
@@ -109,7 +110,7 @@
 assert vertices.ndim == 2
 assert vertices.shape[1] == 2
 
- self.should_simplify = (rcParam['path.simplify'] and
+ self.should_simplify = (rcParams['path.simplify'] and
 (len(vertices) >= 128 and
 (codes is None or np.all(codes <= Path.LINETO))))
 self.has_nonfinite = not np.isfinite(vertices).all()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 14:42:23
Revision: 6712
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6712&view=rev
Author: mdboom
Date: 2008年12月29日 14:42:20 +0000 (2008年12月29日)
Log Message:
-----------
Fix path simplification by a) making it more conservative about when it will simplify based on segment length, and b) honoring path.simplify rcParam in Agg backend.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/config/rcsetup.py
 trunk/matplotlib/lib/matplotlib/path.py
 trunk/matplotlib/lib/matplotlib/rcsetup.py
 trunk/matplotlib/src/agg_py_path_iterator.h
Modified: trunk/matplotlib/lib/matplotlib/config/rcsetup.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/rcsetup.py	2008年12月29日 14:25:47 UTC (rev 6711)
+++ trunk/matplotlib/lib/matplotlib/config/rcsetup.py	2008年12月29日 14:42:20 UTC (rev 6712)
@@ -479,7 +479,7 @@
 'svg.embed_char_paths' : [True, validate_bool], # True to save all characters as paths in the SVG
 'plugins.directory' : ['.matplotlib_plugins', str], # where plugin directory is locate
 
- 'path.simplify' : [False, validate_bool]
+ 'path.simplify' : [True, validate_bool]
 }
 
 if __name__ == '__main__':
Modified: trunk/matplotlib/lib/matplotlib/path.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 14:25:47 UTC (rev 6711)
+++ trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 14:42:20 UTC (rev 6712)
@@ -109,8 +109,9 @@
 assert vertices.ndim == 2
 assert vertices.shape[1] == 2
 
- self.should_simplify = (len(vertices) >= 128 and
- (codes is None or np.all(codes <= Path.LINETO)))
+ self.should_simplify = (rcParam['path.simplify'] and
+ (len(vertices) >= 128 and
+ (codes is None or np.all(codes <= Path.LINETO))))
 self.has_nonfinite = not np.isfinite(vertices).all()
 self.codes = codes
 self.vertices = vertices
Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/rcsetup.py	2008年12月29日 14:25:47 UTC (rev 6711)
+++ trunk/matplotlib/lib/matplotlib/rcsetup.py	2008年12月29日 14:42:20 UTC (rev 6712)
@@ -518,7 +518,7 @@
 'docstring.hardcopy' : [False, validate_bool], # set this when you want to generate hardcopy docstring
 'plugins.directory' : ['.matplotlib_plugins', str], # where plugin directory is locate
 
- 'path.simplify' : [False, validate_bool],
+ 'path.simplify' : [True, validate_bool],
 'agg.path.chunksize' : [0, validate_int] # 0 to disable chunking;
 # recommend about 20000 to
 # enable. Experimental.
Modified: trunk/matplotlib/src/agg_py_path_iterator.h
===================================================================
--- trunk/matplotlib/src/agg_py_path_iterator.h	2008年12月29日 14:25:47 UTC (rev 6711)
+++ trunk/matplotlib/src/agg_py_path_iterator.h	2008年12月29日 14:42:20 UTC (rev 6712)
@@ -353,7 +353,7 @@
 
 //if the perp vector is less than some number of (squared)
 //pixels in size, then merge the current vector
- if (perpdNorm2 < 0.25)
+ if (perpdNorm2 < (1.0 / 9.0))
 {
 //check if the current vector is parallel or
 //anti-parallel to the orig vector. If it is parallel, test
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 14:25:57
Revision: 6711
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6711&view=rev
Author: mdboom
Date: 2008年12月29日 14:25:47 +0000 (2008年12月29日)
Log Message:
-----------
Oops in last commit
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/patches.py
Modified: trunk/matplotlib/lib/matplotlib/patches.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/patches.py	2008年12月29日 14:23:24 UTC (rev 6710)
+++ trunk/matplotlib/lib/matplotlib/patches.py	2008年12月29日 14:25:47 UTC (rev 6711)
@@ -252,7 +252,7 @@
 
 ACCEPTS: [ '/' | '\\' | '|' | '-' | '#' | 'x' ] (ps & pdf backend only)
 """
- self._hatch = h
+ self._hatch = hatch
 
 def get_hatch(self):
 'Return the current hatching pattern'
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 14:23:28
Revision: 6710
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6710&view=rev
Author: mdboom
Date: 2008年12月29日 14:23:24 +0000 (2008年12月29日)
Log Message:
-----------
Update hatch documentation.
Modified Paths:
--------------
 trunk/matplotlib/examples/pylab_examples/hatch_demo.py
 trunk/matplotlib/lib/matplotlib/patches.py
Modified: trunk/matplotlib/examples/pylab_examples/hatch_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 14:10:22 UTC (rev 6709)
+++ trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 14:23:24 UTC (rev 6710)
@@ -1,8 +1,6 @@
 """
-Hatching (pattern filled polygons) is supported currently on PS and PDF
-backend only. See the set_patch method in
-http://matplotlib.sf.net/matplotlib.patches.html#Patch
-for details
+Hatching (pattern filled polygons) is supported currently in the PS,
+PDF, SVG and Agg backends only.
 """
 import matplotlib.pyplot as plt
 
Modified: trunk/matplotlib/lib/matplotlib/patches.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/patches.py	2008年12月29日 14:10:22 UTC (rev 6709)
+++ trunk/matplotlib/lib/matplotlib/patches.py	2008年12月29日 14:23:24 UTC (rev 6710)
@@ -228,11 +228,11 @@
 'return whether fill is set'
 return self.fill
 
- def set_hatch(self, h):
+ def set_hatch(self, hatch):
 """
 Set the hatching pattern
 
- hatch can be one of::
+ *hatch* can be one of::
 
 / - diagonal hatching
 \ - back diagonal
@@ -247,11 +247,9 @@
 
 CURRENT LIMITATIONS:
 
- 1. Hatching is supported in the PostScript and the PDF backend only.
+ 1. Hatching is supported in the PostScript, PDF, SVG and Agg
+ backends only.
 
- 2. Hatching is done with solid black lines of width 0.
-
-
 ACCEPTS: [ '/' | '\\' | '|' | '-' | '#' | 'x' ] (ps & pdf backend only)
 """
 self._hatch = h
@@ -2655,7 +2653,7 @@
 """
 
 path = make_path_regular(path)
- 
+
 if aspect_ratio is not None:
 # Squeeze the given height by the aspect_ratio
 
@@ -2808,27 +2806,27 @@
 [(x3+ddxB, y3+ddyB)]]),
 path.codes)]
 _fillable = [False]
- 
+
 if self.beginarrow:
 if self.fillbegin:
 p = np.concatenate([verticesA, [verticesA[0], verticesA[0]], ])
- c = np.concatenate([codesA, [Path.LINETO, Path.CLOSEPOLY]]) 
+ c = np.concatenate([codesA, [Path.LINETO, Path.CLOSEPOLY]])
 _path.append(Path(p, c))
 _fillable.append(True)
 else:
 _path.append(Path(verticesA, codesA))
 _fillable.append(False)
- 
+
 if self.endarrow:
 if self.fillend:
 _fillable.append(True)
 p = np.concatenate([verticesB, [verticesB[0], verticesB[0]], ])
- c = np.concatenate([codesB, [Path.LINETO, Path.CLOSEPOLY]]) 
+ c = np.concatenate([codesB, [Path.LINETO, Path.CLOSEPOLY]])
 _path.append(Path(p, c))
 else:
 _fillable.append(False)
 _path.append(Path(verticesB, codesB))
- 
+
 return _path, _fillable
 
 
@@ -2926,7 +2924,7 @@
 
 super(ArrowStyle.CurveFilledA, self).__init__( \
 beginarrow=True, endarrow=False,
- fillbegin=True, fillend=False, 
+ fillbegin=True, fillend=False,
 head_length=head_length, head_width=head_width )
 
 _style_list["<|-"] = CurveFilledA
@@ -2948,7 +2946,7 @@
 
 super(ArrowStyle.CurveFilledB, self).__init__( \
 beginarrow=False, endarrow=True,
- fillbegin=False, fillend=True, 
+ fillbegin=False, fillend=True,
 head_length=head_length, head_width=head_width )
 
 _style_list["-|>"] = CurveFilledB
@@ -2970,7 +2968,7 @@
 
 super(ArrowStyle.CurveFilledAB, self).__init__( \
 beginarrow=True, endarrow=True,
- fillbegin=True, fillend=True, 
+ fillbegin=True, fillend=True,
 head_length=head_length, head_width=head_width )
 
 _style_list["<|-|>"] = CurveFilledAB
@@ -3532,7 +3530,7 @@
 
 if cbook.iterable(fillable):
 _path = concatenate_paths(_path)
- 
+
 return self.get_transform().inverted().transform_path(_path)
 
 
@@ -3604,8 +3602,8 @@
 if not cbook.iterable(fillable):
 path = [path]
 fillable = [fillable]
- 
 
+
 affine = transforms.IdentityTransform()
 
 renderer.open_group('patch', self.get_gid())
@@ -3615,6 +3613,6 @@
 renderer.draw_path(gc, p, affine, rgbFace)
 else:
 renderer.draw_path(gc, p, affine, None)
- 
 
+
 renderer.close_group('patch')
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6709
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6709&view=rev
Author: mdboom
Date: 2008年12月29日 14:10:22 +0000 (2008年12月29日)
Log Message:
-----------
Oops in hatch_demo.py
Modified Paths:
--------------
 trunk/matplotlib/examples/pylab_examples/hatch_demo.py
Modified: trunk/matplotlib/examples/pylab_examples/hatch_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 14:08:13 UTC (rev 6708)
+++ trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 14:10:22 UTC (rev 6709)
@@ -12,7 +12,7 @@
 xytext=(0, 5),
 xycoords="axes fraction", textcoords="offset points", ha="center"
 )
-ax1.bar(range(1,5), range(1,5), color='gray', edgecolor='red', hatch="/")
+ax1.bar(range(1,5), range(1,5), color='gray', edgecolor='black', hatch="/")
 
 
 ax2 = fig.add_subplot(122)
@@ -23,5 +23,3 @@
 bar.set_hatch(pattern)
 
 plt.show()
-plt.savefig("test.pdf")
-plt.savefig("test.ps")
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2008年12月29日 14:08:16
Revision: 6708
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6708&view=rev
Author: mdboom
Date: 2008年12月29日 14:08:13 +0000 (2008年12月29日)
Log Message:
-----------
Merge branch 'hatching'
Modified Paths:
--------------
 trunk/matplotlib/examples/pylab_examples/hatch_demo.py
 trunk/matplotlib/lib/matplotlib/backend_bases.py
 trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
 trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
 trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
 trunk/matplotlib/lib/matplotlib/path.py
 trunk/matplotlib/src/_backend_agg.cpp
 trunk/matplotlib/src/_backend_agg.h
Modified: trunk/matplotlib/examples/pylab_examples/hatch_demo.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/examples/pylab_examples/hatch_demo.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -12,7 +12,7 @@
 xytext=(0, 5),
 xycoords="axes fraction", textcoords="offset points", ha="center"
 )
-ax1.bar(range(1,5), range(1,5), color='gray', ecolor='black', hatch="/")
+ax1.bar(range(1,5), range(1,5), color='gray', edgecolor='red', hatch="/")
 
 
 ax2 = fig.add_subplot(122)
@@ -23,3 +23,5 @@
 bar.set_hatch(pattern)
 
 plt.show()
+plt.savefig("test.pdf")
+plt.savefig("test.ps")
Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backend_bases.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/backend_bases.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -30,6 +30,7 @@
 import matplotlib.colors as colors
 import matplotlib.transforms as transforms
 import matplotlib.widgets as widgets
+import matplotlib.path as path
 from matplotlib import rcParams
 
 class RendererBase:
@@ -679,6 +680,14 @@
 """
 return self._hatch
 
+ def get_hatch_path(self, density=6.0):
+ """
+ Returns a Path for the current hatch.
+ """
+ if self._hatch is None:
+ return None
+ return path.Path.hatch(self._hatch, density)
+
 class Event:
 """
 A matplotlib event. Attach additional attributes as defined in
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_agg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_agg.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_agg.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -73,9 +73,13 @@
 'debug-annoying')
 
 def draw_path(self, gc, path, transform, rgbFace=None):
+ """
+ Draw the path
+ """
 nmax = rcParams['agg.path.chunksize'] # here at least for testing
 npts = path.vertices.shape[0]
- if nmax > 100 and npts > nmax and path.should_simplify and rgbFace is None:
+ if (nmax > 100 and npts > nmax and path.should_simplify and
+ rgbFace is None and gc.get_hatch() is None):
 nch = npy.ceil(npts/float(nmax))
 chsize = int(npy.ceil(npts/nch))
 i0 = npy.arange(0, npts, chsize)
@@ -93,7 +97,6 @@
 else:
 self._renderer.draw_path(gc, path, transform, rgbFace)
 
-
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 """
 Draw the math text using matplotlib.mathtext
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -953,21 +953,20 @@
 'CA': alpha, 'ca': alpha })
 return name
 
- def hatchPattern(self, lst):
- pattern = self.hatchPatterns.get(lst, None)
+ def hatchPattern(self, hatch_style):
+ pattern = self.hatchPatterns.get(hatch_style, None)
 if pattern is not None:
 return pattern
 
 name = Name('H%d' % self.nextHatch)
 self.nextHatch += 1
- self.hatchPatterns[lst] = name
+ self.hatchPatterns[hatch_style] = name
 return name
 
 def writeHatches(self):
 hatchDict = dict()
- sidelen = 144.0
- density = 24.0
- for lst, name in self.hatchPatterns.items():
+ sidelen = 72.0
+ for hatch_style, name in self.hatchPatterns.items():
 ob = self.reserveObject('hatch pattern')
 hatchDict[name] = ob
 res = { 'Procsets':
@@ -983,33 +982,21 @@
 # lst is a tuple of stroke color, fill color,
 # number of - lines, number of / lines,
 # number of | lines, number of \ lines
- rgb = lst[0]
+ rgb = hatch_style[0]
 self.output(rgb[0], rgb[1], rgb[2], Op.setrgb_stroke)
- if lst[1] is not None:
- rgb = lst[1]
+ if hatch_style[1] is not None:
+ rgb = hatch_style[1]
 self.output(rgb[0], rgb[1], rgb[2], Op.setrgb_nonstroke,
 0, 0, sidelen, sidelen, Op.rectangle,
 Op.fill)
- if lst[2]: # -
- for j in npy.arange(0.0, sidelen, density/lst[2]):
- self.output(0, j, Op.moveto,
- sidelen, j, Op.lineto)
- if lst[3]: # /
- for j in npy.arange(0.0, sidelen, density/lst[3]):
- self.output(0, j, Op.moveto,
- sidelen-j, sidelen, Op.lineto,
- sidelen-j, 0, Op.moveto,
- sidelen, j, Op.lineto)
- if lst[4]: # |
- for j in npy.arange(0.0, sidelen, density/lst[4]):
- self.output(j, 0, Op.moveto,
- j, sidelen, Op.lineto)
- if lst[5]: # \
- for j in npy.arange(sidelen, 0.0, -density/lst[5]):
- self.output(sidelen, j, Op.moveto,
- j, sidelen, Op.lineto,
- j, 0, Op.moveto,
- 0, j, Op.lineto)
+
+ self.output(0.1, Op.setlinewidth)
+
+ # TODO: We could make this dpi-dependent, but that would be
+ # an API change
+ self.output(*self.pathOperations(
+ Path.hatch(hatch_style[2]),
+ Affine2D().scale(sidelen)))
 self.output(Op.stroke)
 
 self.endStream()
@@ -1735,13 +1722,8 @@
 return [Name('DeviceRGB'), Op.setcolorspace_nonstroke]
 else:
 hatch = hatch.lower()
- lst = ( self._rgb,
- self._fillcolor,
- hatch.count('-') + hatch.count('+'),
- hatch.count('/') + hatch.count('x'),
- hatch.count('|') + hatch.count('+'),
- hatch.count('\\') + hatch.count('x') )
- name = self.file.hatchPattern(lst)
+ hatch_style = (self._rgb, self._fillcolor, hatch)
+ name = self.file.hatchPattern(hatch_style)
 return [Name('Pattern'), Op.setcolorspace_nonstroke,
 name, Op.setcolor_nonstroke]
 
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -31,7 +31,7 @@
 from matplotlib._mathtext_data import uni2type1
 from matplotlib.text import Text
 from matplotlib.path import Path
-from matplotlib.transforms import IdentityTransform
+from matplotlib.transforms import Affine2D
 
 import numpy as npy
 import binascii
@@ -163,7 +163,7 @@
 self.linedash = None
 self.fontname = None
 self.fontsize = None
- self.hatch = None
+ self._hatches = {}
 self.image_magnification = imagedpi/72.0
 self._clip_paths = {}
 self._path_collection_id = 0
@@ -231,58 +231,36 @@
 if store: self.fontname = fontname
 if store: self.fontsize = fontsize
 
- def set_hatch(self, hatch):
- """
- hatch can be one of:
- / - diagonal hatching
- \ - back diagonal
- | - vertical
- - - horizontal
- + - crossed
- X - crossed diagonal
+ def create_hatch(self, hatch):
+ sidelen = 72
+ if self._hatches.has_key(hatch):
+ return self._hatches[hatch]
+ name = 'H%d' % len(self._hatches)
+ self._pswriter.write("""\
+ << /PatternType 1
+ /PaintType 2
+ /TilingType 2
+ /BBox[0 0 %(sidelen)d %(sidelen)d]
+ /XStep %(sidelen)d
+ /YStep %(sidelen)d
 
- letters can be combined, in which case all the specified
- hatchings are done
+ /PaintProc {
+ pop
+ 0 setlinewidth
+""" % locals())
+ self._pswriter.write(
+ self._convert_path(Path.hatch(hatch), Affine2D().scale(72.0)))
+ self._pswriter.write("""\
+ stroke
+ } bind
+ >>
+ matrix
+ makepattern
+ /%(name)s exch def
+""" % locals())
+ self._hatches[hatch] = name
+ return name
 
- if same letter repeats, it increases the density of hatching
- in that direction
- """
- hatches = {'horiz':0, 'vert':0, 'diag1':0, 'diag2':0}
-
- for letter in hatch:
- if (letter == '/'): hatches['diag2'] += 1
- elif (letter == '\\'): hatches['diag1'] += 1
- elif (letter == '|'): hatches['vert'] += 1
- elif (letter == '-'): hatches['horiz'] += 1
- elif (letter == '+'):
- hatches['horiz'] += 1
- hatches['vert'] += 1
- elif (letter.lower() == 'x'):
- hatches['diag1'] += 1
- hatches['diag2'] += 1
-
- def do_hatch(angle, density):
- if (density == 0): return ""
- return """\
- gsave
- eoclip %s rotate 0.0 0.0 0.0 0.0 setrgbcolor 0 setlinewidth
- /hatchgap %d def
- pathbbox /hatchb exch def /hatchr exch def /hatcht exch def /hatchl exch def
- hatchl cvi hatchgap idiv hatchgap mul
- hatchgap
- hatchr cvi hatchgap idiv hatchgap mul
- {hatcht m 0 hatchb hatcht sub r }
- for
- stroke
- grestore
- """ % (angle, 12/density)
- self._pswriter.write("gsave\n")
- self._pswriter.write(do_hatch(90, hatches['horiz']))
- self._pswriter.write(do_hatch(0, hatches['vert']))
- self._pswriter.write(do_hatch(45, hatches['diag1']))
- self._pswriter.write(do_hatch(-45, hatches['diag2']))
- self._pswriter.write("grestore\n")
-
 def get_canvas_width_height(self):
 'return the canvas width and height in display coords'
 return self.width, self.height
@@ -816,15 +794,17 @@
 if fill:
 if stroke:
 write("gsave\n")
- self.set_color(store=0, *rgbFace[:3])
- write("fill\ngrestore\n")
- else:
- self.set_color(store=0, *rgbFace[:3])
- write("fill\n")
+ self.set_color(store=0, *rgbFace[:3])
+ write("fill\n")
+ if stroke:
+ write("grestore\n")
 
 hatch = gc.get_hatch()
 if hatch:
- self.set_hatch(hatch)
+ hatch_name = self.create_hatch(hatch)
+ write("gsave\n")
+ write("[/Pattern [/DeviceRGB]] setcolorspace %f %f %f " % gc.get_rgb()[:3])
+ write("%s setcolor fill grestore\n" % hatch_name)
 
 if stroke:
 write("stroke\n")
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -57,6 +57,7 @@
 self._markers = {}
 self._path_collection_id = 0
 self._imaged = {}
+ self._hatchd = {}
 self.mathtext_parser = MathTextParser('SVG')
 svgwriter.write(svgProlog%(width,height,width,height))
 
@@ -90,15 +91,38 @@
 font.set_size(size, 72.0)
 return font
 
+ def _get_hatch(self, gc, rgbFace):
+ """
+ Create a new hatch pattern
+ """
+ HATCH_SIZE = 144
+ dictkey = (gc.get_hatch().lower(), rgbFace, gc.get_rgb())
+ id = self._hatchd.get(dictkey)
+ if id is None:
+ id = 'h%s' % md5(str(dictkey)).hexdigest()
+ self._svgwriter.write('<defs>\n <pattern id="%s" ' % id)
+ self._svgwriter.write('patternUnits="userSpaceOnUse" x="0" y="0" ')
+ self._svgwriter.write(' width="%d" height="%d" >\n' % (HATCH_SIZE, HATCH_SIZE))
+ path_data = self._convert_path(gc.get_hatch_path(), Affine2D().scale(144))
+ path = '<path d="%s" fill="%s" stroke="%s" stroke-width="1.0"/>' % (
+ path_data, rgb2hex(rgbFace[:3]), rgb2hex(gc.get_rgb()[:3]))
+ self._svgwriter.write(path)
+ self._svgwriter.write('\n </pattern>\n</defs>')
+ self._hatchd[dictkey] = id
+ return id
+
 def _get_style(self, gc, rgbFace):
 """
 return the style string.
 style is generated from the GraphicsContext, rgbFace and clippath
 """
- if rgbFace is None:
- fill = 'none'
+ if gc.get_hatch() is not None:
+ fill = "url(#%s)" % self._get_hatch(gc, rgbFace)
 else:
- fill = rgb2hex(rgbFace[:3])
+ if rgbFace is None:
+ fill = 'none'
+ else:
+ fill = rgb2hex(rgbFace[:3])
 
 offset, seq = gc.get_dashes()
 if seq is None:
@@ -150,7 +174,7 @@
 def open_group(self, s, gid=None):
 """
 Open a grouping element with label *s*. If *gid* is given, use
- *gid* as the id of the group. 
+ *gid* as the id of the group.
 """
 if gid:
 self._svgwriter.write('<g id="%s">\n' % (gid))
Modified: trunk/matplotlib/lib/matplotlib/path.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/lib/matplotlib/path.py	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -11,7 +11,7 @@
 from matplotlib._path import point_in_path, get_path_extents, \
 point_in_path_collection, get_path_collection_extents, \
 path_in_path, path_intersects_path, convert_path_to_polygons
-from matplotlib.cbook import simple_linear_interpolation
+from matplotlib.cbook import simple_linear_interpolation, maxdict
 
 class Path(object):
 """
@@ -115,8 +115,8 @@
 self.codes = codes
 self.vertices = vertices
 
- #@staticmethod
- def make_compound_path(*args):
+ #@classmethod
+ def make_compound_path(cls, *args):
 """
 (staticmethod) Make a compound path from a list of Path
 objects. Only polygons (not curves) are supported.
@@ -130,14 +130,14 @@
 vertices = np.vstack([x.vertices for x in args])
 vertices.reshape((total_length, 2))
 
- codes = Path.LINETO * np.ones(total_length)
+ codes = cls.LINETO * np.ones(total_length)
 i = 0
 for length in lengths:
- codes[i] = Path.MOVETO
+ codes[i] = cls.MOVETO
 i += length
 
- return Path(vertices, codes)
- make_compound_path = staticmethod(make_compound_path)
+ return cls(vertices, codes)
+ make_compound_path = classmethod(make_compound_path)
 
 def __repr__(self):
 return "Path(%s, %s)" % (self.vertices, self.codes)
@@ -343,7 +343,7 @@
 """
 if cls._unit_rectangle is None:
 cls._unit_rectangle = \
- Path([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]])
+ cls([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0], [0.0, 0.0]])
 return cls._unit_rectangle
 unit_rectangle = classmethod(unit_rectangle)
 
@@ -366,7 +366,7 @@
 # "points-up"
 theta += np.pi / 2.0
 verts = np.concatenate((np.cos(theta), np.sin(theta)), 1)
- path = Path(verts)
+ path = cls(verts)
 cls._unit_regular_polygons[numVertices] = path
 return path
 unit_regular_polygon = classmethod(unit_regular_polygon)
@@ -392,7 +392,7 @@
 r = np.ones(ns2 + 1)
 r[1::2] = innerCircle
 verts = np.vstack((r*np.cos(theta), r*np.sin(theta))).transpose()
- path = Path(verts)
+ path = cls(verts)
 cls._unit_regular_polygons[(numVertices, innerCircle)] = path
 return path
 unit_regular_star = classmethod(unit_regular_star)
@@ -466,7 +466,7 @@
 codes[0] = cls.MOVETO
 codes[-1] = cls.CLOSEPOLY
 
- cls._unit_circle = Path(vertices, codes)
+ cls._unit_circle = cls(vertices, codes)
 return cls._unit_circle
 unit_circle = classmethod(unit_circle)
 
@@ -523,19 +523,19 @@
 
 if is_wedge:
 length = n * 3 + 4
- vertices = np.zeros((length, 2), np.float_)
- codes = Path.CURVE4 * np.ones((length, ), Path.code_type)
+ vertices = np.empty((length, 2), np.float_)
+ codes = cls.CURVE4 * np.ones((length, ), cls.code_type)
 vertices[1] = [xA[0], yA[0]]
- codes[0:2] = [Path.MOVETO, Path.LINETO]
- codes[-2:] = [Path.LINETO, Path.CLOSEPOLY]
+ codes[0:2] = [cls.MOVETO, cls.LINETO]
+ codes[-2:] = [cls.LINETO, cls.CLOSEPOLY]
 vertex_offset = 2
 end = length - 2
 else:
 length = n * 3 + 1
- vertices = np.zeros((length, 2), np.float_)
- codes = Path.CURVE4 * np.ones((length, ), Path.code_type)
+ vertices = np.empty((length, 2), np.float_)
+ codes = cls.CURVE4 * np.ones((length, ), cls.code_type)
 vertices[0] = [xA[0], yA[0]]
- codes[0] = Path.MOVETO
+ codes[0] = cls.MOVETO
 vertex_offset = 1
 end = length
 
@@ -546,7 +546,7 @@
 vertices[vertex_offset+2:end:3, 0] = xB
 vertices[vertex_offset+2:end:3, 1] = yB
 
- return Path(vertices, codes)
+ return cls(vertices, codes)
 arc = classmethod(arc)
 
 #@classmethod
@@ -562,6 +562,94 @@
 return cls.arc(theta1, theta2, n, True)
 wedge = classmethod(wedge)
 
+ _hatch_dict = maxdict(8)
+ #@classmethod
+ def hatch(cls, hatchpattern, density=6):
+ """
+ Given a hatch specifier, *hatchpattern*, generates a Path that
+ can be used in a repeated hatching pattern. *density* is the
+ number of lines per unit square.
+ """
+ if hatchpattern is None:
+ return None
+
+ hatch = hatchpattern.lower()
+ hatch_path = cls._hatch_dict.get((hatch, density))
+ if hatch_path is not None:
+ return hatch_path
+
+ size = 1.0
+ density = int(density)
+ counts = [
+ hatch.count('-') + hatch.count('+'),
+ hatch.count('/') + hatch.count('x'),
+ hatch.count('|') + hatch.count('+'),
+ hatch.count('\\') + hatch.count('x')
+ ]
+
+ if sum(counts) == 0:
+ return cls([])
+
+ counts = [x * density for x in counts]
+
+ num_vertices = (counts[0] * 2 + counts[1] * 4 +
+ counts[2] * 2 + counts[3] * 4)
+ vertices = np.empty((num_vertices, 2))
+ codes = np.empty((num_vertices,), cls.code_type)
+ codes[0::2] = cls.MOVETO
+ codes[1::2] = cls.LINETO
+
+ cursor = 0
+
+ if counts[0]:
+ vertices_chunk = vertices[cursor:cursor + counts[0] * 2]
+ cursor += counts[0] * 2
+ steps = np.linspace(0.0, 1.0, counts[0], False)
+ vertices_chunk[0::2, 0] = 0.0
+ vertices_chunk[0::2, 1] = steps
+ vertices_chunk[1::2, 0] = size
+ vertices_chunk[1::2, 1] = steps
+
+ if counts[1]:
+ vertices_chunk = vertices[cursor:cursor + counts[1] * 4]
+ cursor += counts[1] * 4
+ steps = np.linspace(0.0, 1.0, counts[1], False)
+ vertices_chunk[0::4, 0] = 0.0
+ vertices_chunk[0::4, 1] = steps
+ vertices_chunk[1::4, 0] = size - steps
+ vertices_chunk[1::4, 1] = size
+ vertices_chunk[2::4, 0] = size - steps
+ vertices_chunk[2::4, 1] = 0.0
+ vertices_chunk[3::4, 0] = size
+ vertices_chunk[3::4, 1] = steps
+
+ if counts[2]:
+ vertices_chunk = vertices[cursor:cursor + counts[2] * 2]
+ cursor += counts[2] * 2
+ steps = np.linspace(0.0, 1.0, counts[2], False)
+ vertices_chunk[0::2, 0] = steps
+ vertices_chunk[0::2, 1] = 0.0
+ vertices_chunk[1::2, 0] = steps
+ vertices_chunk[1::2, 1] = size
+
+ if counts[3]:
+ vertices_chunk = vertices[cursor:cursor + counts[3] * 4]
+ cursor += counts[3] * 4
+ steps = np.linspace(0.0, 1.0, counts[3], False)
+ vertices_chunk[0::4, 0] = size
+ vertices_chunk[0::4, 1] = steps
+ vertices_chunk[1::4, 0] = steps
+ vertices_chunk[1::4, 1] = size
+ vertices_chunk[2::4, 0] = steps
+ vertices_chunk[2::4, 1] = 0.0
+ vertices_chunk[3::4, 0] = 0.0
+ vertices_chunk[3::4, 1] = steps
+
+ hatch_path = cls(vertices, codes)
+ cls._hatch_dict[(hatch, density)] = hatch_path
+ return hatch_path
+ hatch = classmethod(hatch)
+
 _get_path_collection_extents = get_path_collection_extents
 def get_path_collection_extents(*args):
 """
Modified: trunk/matplotlib/src/_backend_agg.cpp
===================================================================
--- trunk/matplotlib/src/_backend_agg.cpp	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/src/_backend_agg.cpp	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -30,6 +30,7 @@
 #include "agg_span_image_filter_gray.h"
 #include "agg_span_image_filter_rgba.h"
 #include "agg_span_interpolator_linear.h"
+#include "agg_span_pattern_rgba.h"
 #include "agg_conv_shorten_path.h"
 #include "util/agg_color_conv_rgb8.h"
 
@@ -149,6 +150,7 @@
 _set_clip_rectangle(gc);
 _set_clip_path(gc);
 _set_snap(gc);
+ _set_hatch_path(gc);
 }
 
 GCAgg::GCAgg(double dpi) :
@@ -273,6 +275,15 @@
 }
 }
 
+void
+GCAgg::_set_hatch_path( const Py::Object& gc) {
+ _VERBOSE("GCAgg::_set_hatch_path");
+
+ Py::Object method_obj = gc.getAttr("get_hatch_path");
+ Py::Callable method(method_obj);
+ hatchpath = method.apply(Py::Tuple());
+}
+
 const size_t
 RendererAgg::PIXELS_PER_INCH(96);
 
@@ -310,6 +321,7 @@
 rendererBase.clear(agg::rgba(1, 1, 1, 0));
 rendererAA.attach(rendererBase);
 rendererBin.attach(rendererBase);
+ hatchRenderingBuffer.attach(hatchBuffer, HATCH_SIZE, HATCH_SIZE, HATCH_SIZE*4);
 }
 
 void RendererAgg::create_alpha_buffers() {
@@ -879,6 +891,55 @@
 }
 }
 
+ // Render hatch
+ if (!gc.hatchpath.isNone()) {
+ // Reset any clipping that may be in effect, since we'll be
+ // drawing the hatch in a scratch buffer at origin (0, 0)
+ theRasterizer.reset_clipping();
+ rendererBase.reset_clipping(true);
+
+ // Create and transform the path
+ typedef agg::conv_transform<PathIterator> hatch_path_trans_t;
+ typedef SimplifyPath<hatch_path_trans_t> hatch_path_simplify_t;
+ typedef agg::conv_stroke<hatch_path_simplify_t> hatch_path_stroke_t;
+
+ PathIterator hatch_path(gc.hatchpath);
+ agg::trans_affine hatch_trans;
+ hatch_trans *= agg::trans_affine_scaling(HATCH_SIZE, HATCH_SIZE);
+ hatch_path_trans_t hatch_path_trans(hatch_path, hatch_trans);
+ hatch_path_simplify_t hatch_path_simplify
+ (hatch_path_trans, true, false, HATCH_SIZE, HATCH_SIZE);
+ hatch_path_stroke_t hatch_path_stroke(hatch_path_simplify);
+ hatch_path_stroke.width(1.0);
+ hatch_path_stroke.line_cap(agg::square_cap);
+ theRasterizer.add_path(hatch_path_stroke);
+
+ // Render the path into the hatch buffer
+ pixfmt hatch_img_pixf(hatchRenderingBuffer);
+ renderer_base rb(hatch_img_pixf);
+ renderer_aa rs(rb);
+ rb.clear(agg::rgba(0.0, 0.0, 0.0, 0.0));
+ rs.color(gc.color);
+ agg::render_scanlines(theRasterizer, slineP8, rs);
+
+ // Put clipping back on, if originally set on entry to this
+ // function
+ set_clipbox(gc.cliprect, theRasterizer);
+ if (has_clippath)
+ render_clippath(gc.clippath, gc.clippath_trans);
+
+ // Transfer the hatch to the main image buffer
+ typedef agg::image_accessor_wrap<pixfmt,
+ agg::wrap_mode_repeat_auto_pow2,
+ agg::wrap_mode_repeat_auto_pow2> img_source_type;
+ typedef agg::span_pattern_rgba<img_source_type> span_gen_type;
+ agg::span_allocator<agg::rgba8> sa;
+ img_source_type img_src(hatch_img_pixf);
+ span_gen_type sg(img_src, 0, 0);
+ theRasterizer.add_path(path);
+ agg::render_scanlines_aa(theRasterizer, slineP8, rendererBase, sa, sg);
+ }
+
 // Render stroke
 if (gc.linewidth != 0.0) {
 double linewidth = gc.linewidth;
Modified: trunk/matplotlib/src/_backend_agg.h
===================================================================
--- trunk/matplotlib/src/_backend_agg.h	2008年12月29日 13:58:18 UTC (rev 6707)
+++ trunk/matplotlib/src/_backend_agg.h	2008年12月29日 14:08:13 UTC (rev 6708)
@@ -60,7 +60,6 @@
 typedef agg::scanline_bin scanline_bin;
 typedef agg::amask_no_clip_gray8 alpha_mask_type;
 
-
 typedef agg::renderer_base<agg::pixfmt_gray8> renderer_base_alpha_mask_type;
 typedef agg::renderer_scanline_aa_solid<renderer_base_alpha_mask_type> renderer_alpha_mask_type;
 
@@ -129,6 +128,8 @@
 SNAP_TRUE
 } snap;
 
+ Py::Object hatchpath;
+
 protected:
 agg::rgba get_color(const Py::Object& gc);
 double points_to_pixels( const Py::Object& points);
@@ -139,6 +140,7 @@
 void _set_clip_path( const Py::Object& gc);
 void _set_antialiased( const Py::Object& gc);
 void _set_snap( const Py::Object& gc);
+ void _set_hatch_path( const Py::Object& gc);
 };
 
 
@@ -206,6 +208,12 @@
 Py::Object lastclippath;
 agg::trans_affine lastclippath_transform;
 
+ // HATCH_SIZE should be a power of 2, to take advantage of Agg's
+ // fast pattern rendering
+ static const size_t HATCH_SIZE = 128;
+ agg::int8u hatchBuffer[HATCH_SIZE * HATCH_SIZE * 4];
+ agg::rendering_buffer hatchRenderingBuffer;
+
 const int debug;
 
 protected:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6707
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6707&view=rev
Author: jouni
Date: 2008年12月29日 13:58:18 +0000 (2008年12月29日)
Log Message:
-----------
Fix bug in earlier bugfix
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月29日 13:48:51 UTC (rev 6706)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月29日 13:58:18 UTC (rev 6707)
@@ -528,7 +528,8 @@
 # TODO: font effects such as SlantFont
 matplotlib.verbose.report(
 'Embedding Type 1 font ' + fontinfo.fontfile +
- ' with encoding ' + fontinfo.encodingfile, 'debug')
+ ' with encoding ' + (fontinfo.encodingfile or '(none)'),
+ 'debug')
 
 # Use FT2Font to get several font properties
 font = FT2Font(fontinfo.fontfile)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jo...@us...> - 2008年12月29日 13:49:02
Revision: 6706
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6706&view=rev
Author: jouni
Date: 2008年12月29日 13:48:51 +0000 (2008年12月29日)
Log Message:
-----------
Fix a bug in pdf usetex support
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2008年12月28日 16:07:10 UTC (rev 6705)
+++ trunk/matplotlib/CHANGELOG	2008年12月29日 13:48:51 UTC (rev 6706)
@@ -1,3 +1,7 @@
+2008年12月29日 Fix a bug in pdf usetex support, which occurred if the same
+ Type-1 font was used with different encodings, e.g. with
+ Minion Pro and MnSymbol. - JKS
+
 2008年12月20日 fix the dpi-dependent offset of Shadow. - JJL
 
 2008年12月20日 fix the hatch bug in the pdf backend. minor update
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月28日 16:07:10 UTC (rev 6705)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2008年12月29日 13:48:51 UTC (rev 6706)
@@ -394,10 +394,11 @@
 'Contents': contentObject }
 self.writeObject(thePageObject, thePage)
 
- # self.fontNames maps filenames to internal font names
- self.fontNames = {}
+ self.fontNames = {} # maps filenames to internal font names
 self.nextFont = 1 # next free internal font name
- self.fontInfo = {} # information on fonts: metrics, encoding
+ self.dviFontInfo = {} # information on dvi fonts
+ self.type1Descriptors = {} # differently encoded Type-1 fonts may
+ # share the same descriptor
 
 self.alphaStates = {} # maps alpha values to graphics state objects
 self.nextAlphaState = 1
@@ -474,7 +475,7 @@
 """
 Select a font based on fontprop and return a name suitable for
 Op.selectfont. If fontprop is a string, it will be interpreted
- as the filename of the font.
+ as the filename (or dvi name) of the font.
 """
 
 if is_string_like(fontprop):
@@ -496,17 +497,18 @@
 fonts = {}
 for filename, Fx in self.fontNames.items():
 if filename.endswith('.afm'):
+ # from pdf.use14corefonts
 fontdictObject = self._write_afm_font(filename)
- elif filename.endswith('.pfb') or filename.endswith('.pfa'):
- # a Type 1 font; limited support for now
- fontdictObject = self.embedType1(filename, self.fontInfo[Fx])
+ elif self.dviFontInfo.has_key(filename):
+ # a Type 1 font from a dvi file
+ fontdictObject = self.embedType1(filename, self.dviFontInfo[filename])
 else:
+ # a normal TrueType font
 realpath, stat_key = get_realpath_and_stat(filename)
 chars = self.used_characters.get(stat_key)
 if chars is not None and len(chars[1]):
 fontdictObject = self.embedTTF(realpath, chars[1])
 fonts[Fx] = fontdictObject
- #print >>sys.stderr, filename
 self.writeObject(self.fontObject, fonts)
 
 def _write_afm_font(self, filename):
@@ -522,36 +524,40 @@
 self.writeObject(fontdictObject, fontdict)
 return fontdictObject
 
- def embedType1(self, filename, fontinfo):
+ def embedType1(self, texname, fontinfo):
 # TODO: font effects such as SlantFont
- fh = open(filename, 'rb')
 matplotlib.verbose.report(
- 'Embedding Type 1 font ' + filename, 'debug')
- try:
- fontdata = fh.read()
- finally:
- fh.close()
+ 'Embedding Type 1 font ' + fontinfo.fontfile +
+ ' with encoding ' + fontinfo.encodingfile, 'debug')
 
- font = FT2Font(filename)
+ # Use FT2Font to get several font properties
+ font = FT2Font(fontinfo.fontfile)
 
- widthsObject, fontdescObject, fontdictObject, fontfileObject = \
- [ self.reserveObject(n) for n in
- ('font widths', 'font descriptor',
- 'font dictionary', 'font file') ]
+ # Font descriptors may be shared between differently encoded
+ # Type-1 fonts, so only create a new descriptor if there is no
+ # existing descriptor for this font.
+ fontdesc = self.type1Descriptors.get(fontinfo.fontfile)
+ if fontdesc is None:
+ fontdesc = self.createType1Descriptor(font, fontinfo.fontfile)
+ self.type1Descriptors[fontinfo.fontfile] = fontdesc
 
- firstchar = 0
- lastchar = len(fontinfo.widths) - 1
+ # Widths
+ widthsObject = self.reserveObject('font widths')
+ self.writeObject(widthsObject, fontinfo.widths)
 
+ # Font dictionary
+ fontdictObject = self.reserveObject('font dictionary')
 fontdict = {
 'Type': Name('Font'),
 'Subtype': Name('Type1'),
 'BaseFont': Name(font.postscript_name),
 'FirstChar': 0,
- 'LastChar': lastchar,
+ 'LastChar': len(fontinfo.widths) - 1,
 'Widths': widthsObject,
- 'FontDescriptor': fontdescObject,
+ 'FontDescriptor': fontdesc,
 }
 
+ # Encoding (if needed)
 if fontinfo.encodingfile is not None:
 enc = dviread.Encoding(fontinfo.encodingfile)
 differencesArray = [ Name(ch) for ch in enc ]
@@ -561,6 +567,15 @@
 'Differences': differencesArray },
 })
 
+ self.writeObject(fontdictObject, fontdict)
+ return fontdictObject
+
+ def createType1Descriptor(self, font, fontfile):
+ # Create and write the font descriptor and the font file
+ # of a Type-1 font
+ fontdescObject = self.reserveObject('font descriptor')
+ fontfileObject = self.reserveObject('font file')
+
 _, _, fullname, familyname, weight, italic_angle, fixed_pitch, \
 ul_position, ul_thickness = font.get_ps_font_info()
 
@@ -591,11 +606,9 @@
 #'FontWeight': a number where 400 = Regular, 700 = Bold
 }
 
- self.writeObject(fontdictObject, fontdict)
- self.writeObject(widthsObject, fontinfo.widths)
 self.writeObject(fontdescObject, descriptor)
 
- t1font = type1font.Type1Font(filename)
+ t1font = type1font.Type1Font(fontfile)
 self.beginStream(fontfileObject.id, None,
 { 'Length1': len(t1font.parts[0]),
 'Length2': len(t1font.parts[1]),
@@ -604,7 +617,7 @@
 self.currentstream.write(t1font.parts[1])
 self.endStream()
 
- return fontdictObject
+ return fontdescObject
 
 def _get_xobject_symbol_name(self, filename, symbol_name):
 return "%s-%s" % (
@@ -1362,13 +1375,15 @@
 oldfont, seq = None, []
 for x1, y1, dvifont, glyph, width in page.text:
 if dvifont != oldfont:
- psfont = self.tex_font_mapping(dvifont.texname)
- pdfname = self.file.fontName(psfont.filename)
- if self.file.fontInfo.get(pdfname, None) is None:
- self.file.fontInfo[pdfname] = Bunch(
+ pdfname = self.file.fontName(dvifont.texname)
+ if not self.file.dviFontInfo.has_key(dvifont.texname):
+ psfont = self.tex_font_mapping(dvifont.texname)
+ self.file.dviFontInfo[dvifont.texname] = Bunch(
+ fontfile=psfont.filename,
 encodingfile=psfont.encoding,
 widths=dvifont.widths,
 dvifont=dvifont)
+ # TODO: font effects
 seq += [['font', pdfname, dvifont.size]]
 oldfont = dvifont
 seq += [['text', x1, y1, [chr(glyph)], x1+width]]
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 6705
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6705&view=rev
Author: jswhit
Date: 2008年12月28日 16:07:10 +0000 (2008年12月28日)
Log Message:
-----------
simplify calculation of geostationary limb
Modified Paths:
--------------
 trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
Modified: trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py
===================================================================
--- trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月26日 23:20:56 UTC (rev 6704)
+++ trunk/toolkits/basemap/lib/mpl_toolkits/basemap/proj.py	2008年12月28日 16:07:10 UTC (rev 6705)
@@ -94,20 +94,21 @@
 elif self.projection == 'geos':
 self._proj4 = pyproj.Proj(projparams)
 # find major and minor axes of ellipse defining map proj region.
- delta = 0.01
- lats = np.arange(0,90,delta)
- lon_0 = projparams['lon_0']
- lons = lon_0*np.ones(len(lats),'d')
- x, y = self._proj4(lons, lats)
- yi = (y > 1.e20).tolist()
- ny = yi.index(1)-1
- height = y[ny]
- lons = np.arange(lon_0,lon_0+90,delta)
- lats = np.zeros(len(lons),'d')
- x, y = self(lons, lats)
- xi = (x > 1.e20).tolist()
- nx = xi.index(1)-1
- width = x[nx]
+ # h is measured from surface of earth at equator.
+ h = projparams['h'] + self.rmajor
+ # latitude of horizon on central meridian
+ lonmax = 90.-(180./np.pi)*np.arcsin(self.rmajor/h)
+ # longitude of horizon on equator
+ latmax = 90.-(180./np.pi)*np.arcsin(self.rminor/h)
+ # truncate to nearest hundredth of a degree (to make sure
+ # they aren't slightly over the horizon)
+ latmax = int(100*latmax)/100. 
+ lonmax = int(100*lonmax)/100. 
+ # width and height of visible projection
+ P = pyproj.Proj(proj='geos',a=self.rmajor,\
+ b=self.rminor,lat_0=0,lon_0=0,h=projparams['h'])
+ x1,y1 = P(0.,latmax); x2,y2 = P(lonmax,0.)
+ width = x2; height = y1
 self._height = height
 self._width = width
 if (llcrnrlon == -180 and llcrnrlat == -90 and
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

Showing results of 271

1 2 3 .. 11 > >> (Page 1 of 11)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /