From: <jd...@us...> - 2009-08-04 13:20:40
|
Revision: 7346 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7346&view=rev Author: jdh2358 Date: 2009-08-04 13:20:29 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Merged revisions 7323-7326,7328-7331,7334-7337,7343 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_99_maint ........ r7323 | jdh2358 | 2009-07-31 10:32:11 -0500 (Fri, 31 Jul 2009) | 2 lines apply sf patches 2830233 and 2823885 for osx setup and 64 bit; thanks Michiel ........ r7324 | jdh2358 | 2009-07-31 10:39:30 -0500 (Fri, 31 Jul 2009) | 1 line revert setupext.py patch for osx; breaks my osx test build ........ r7325 | jdh2358 | 2009-07-31 10:52:19 -0500 (Fri, 31 Jul 2009) | 1 line added miktex win32 patch from sf patch 2820194 ........ r7326 | jdh2358 | 2009-07-31 13:11:50 -0500 (Fri, 31 Jul 2009) | 1 line update the makefile for win32 build ........ r7328 | jdh2358 | 2009-08-01 12:37:26 -0500 (Sat, 01 Aug 2009) | 1 line Applied Michiel's sf patch 2823885 to remove the /usr/X11R6 dirs from darwin ........ r7329 | jdh2358 | 2009-08-01 14:11:58 -0500 (Sat, 01 Aug 2009) | 1 line some fixes for the binary builds ........ r7330 | jdh2358 | 2009-08-01 14:27:43 -0500 (Sat, 01 Aug 2009) | 1 line more fixes for osx ........ r7331 | jdh2358 | 2009-08-01 14:34:05 -0500 (Sat, 01 Aug 2009) | 1 line update the readme with build requirements ........ r7334 | jdh2358 | 2009-08-03 11:38:25 -0500 (Mon, 03 Aug 2009) | 1 line handled sf bugs 2831556 and 2830525; better bar error messages and backend driver configs ........ r7335 | jdh2358 | 2009-08-03 12:19:42 -0500 (Mon, 03 Aug 2009) | 1 line added two examples from Josh Hemann ........ r7336 | jdh2358 | 2009-08-03 12:40:17 -0500 (Mon, 03 Aug 2009) | 1 line fixed rec2csv win32 file handle bug from sf patch 2831018 ........ r7337 | jdh2358 | 2009-08-03 14:31:05 -0500 (Mon, 03 Aug 2009) | 1 line removed a couple of cases of mlab.load ........ r7343 | jdh2358 | 2009-08-04 06:50:09 -0500 (Tue, 04 Aug 2009) | 1 line applied sf patch 2815064 (middle button events for wx) and patch 2818092 (resize events for wx) ........ Modified Paths: -------------- trunk/matplotlib/doc/_templates/index.html trunk/matplotlib/doc/_templates/indexsidebar.html trunk/matplotlib/doc/api/spine_api.rst trunk/matplotlib/doc/faq/installing_faq.rst trunk/matplotlib/doc/pyplots/plotmap.py trunk/matplotlib/doc/users/installing.rst trunk/matplotlib/examples/pylab_examples/load_converter.py trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/backends/backend_wx.py trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/lib/matplotlib/texmanager.py trunk/matplotlib/release/osx/Makefile trunk/matplotlib/release/osx/README.txt trunk/matplotlib/release/win32/Makefile trunk/matplotlib/setupext.py trunk/matplotlib/src/_macosx.m Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/barchart_demo2.py trunk/matplotlib/examples/pylab_examples/boxplot_demo2.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/mathtex:1-7263 /branches/v0_98_5_maint:1-7253 /branches/v0_99_maint:1-7318,7338 + /branches/mathtex:1-7263 /branches/v0_98_5_maint:1-7253 /branches/v0_99_maint:1-7345 Modified: trunk/matplotlib/doc/_templates/index.html =================================================================== --- trunk/matplotlib/doc/_templates/index.html 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/_templates/index.html 2009-08-04 13:20:29 UTC (rev 7346) @@ -3,7 +3,7 @@ {% block body %} - <h1>Welcome</h1> + <h1>mpl</h1> <p>matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and Modified: trunk/matplotlib/doc/_templates/indexsidebar.html =================================================================== --- trunk/matplotlib/doc/_templates/indexsidebar.html 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/_templates/indexsidebar.html 2009-08-04 13:20:29 UTC (rev 7346) @@ -4,11 +4,14 @@ <p>Please <a href="http://sourceforge.net/project/project_donations.php?group_id=80706">donate</a> to support matplotlib development.</p> +<p>A release candidate rc1 of matplotlib-0.99.0 is <a href="http://drop.io/xortel1#">available</a> for testing. Please post any bugs to the <a href="http://sourceforge.net/tracker2/?group_id=80706">tracker</a> +</p> <p>Watch a <a href="http://videolectures.net/mloss08_hunter_mat">video lecture</a> about matplotlib presented at <a href="http://videolectures.net/mloss08_whistler">NIPS 08 Workshop</a> <i>Machine Learning Open Source Software</i></a>. </p> <h3>Download</h3> + <p>Current version: <b>{{ version }}</b></p> Modified: trunk/matplotlib/doc/api/spine_api.rst =================================================================== --- trunk/matplotlib/doc/api/spine_api.rst 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/api/spine_api.rst 2009-08-04 13:20:29 UTC (rev 7346) @@ -4,7 +4,7 @@ :mod:`matplotlib.spine` -====================== +======================== .. automodule:: matplotlib.spine :members: Modified: trunk/matplotlib/doc/faq/installing_faq.rst =================================================================== --- trunk/matplotlib/doc/faq/installing_faq.rst 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/faq/installing_faq.rst 2009-08-04 13:20:29 UTC (rev 7346) @@ -287,11 +287,66 @@ <http://www.python.org/download/>`_. +.. _install_osx_binaries: + +Installing OSX binaries +----------------------- + +If you want to install matplotlib from one of the binary installers we +build, you have two choices: a mpkg installer, which is a typical +Installer.app, or an binary OSX egg, which you can install via +setuptools easy_install. + +The mkpg installer will have a "zip" extension, and will have a name +like file:`matplotlib-0.99.0.rc1-py2.5-macosx10.5_mpkg.zip` depending on +the python, matplotlib, and OSX versions. You need to unzip this file +using either the "unzip" command on OSX, or simply double clicking on +it to run StuffIt Expander. When you double click on the resultant +mpkd directory, which will have a name like +file:`matplotlib-0.99.0.rc1-py2.5-macosx10.5.mpkg`, it will run the +Installer.app, prompt you for a password if you need system wide +installation privileges, and install to a directory like +file:`/Library/Python/2.5/site-packages/`, again depedending on your +python version. This directory may not be in your python path, so you +can test your installation with:: + + > python -c 'import matplotlib; print matplotlib.__version__, matplotlib.__file__' + +If you get an error like:: + + Traceback (most recent call last): + File "<string>", line 1, in <module> + ImportError: No module named matplotlib + +then you will need to set your PYTHONPATH, eg:: + + export PYTHONPATH=/Library/Python/2.5/site-packages:$PYTHONPATH + +See also ref:`environment-variables`. + .. _easy-install-osx-egg: -easy_install from egg? +easy_install from egg ------------------------------ +You can also us the eggs we build for OSX (see the `installation +instructions +<http://pypi.python.org/pypi/setuptools#cygwin-mac-os-x-linux-other>`_ +for easy_install if you do not have it on your system already). You +can try:: + + > easy_install matplotlib + +which should grab the latest egg from the sourceforge site, but the +naming conventions for OSX eggs appear to be broken (see below) so +there is no guarantee the right egg will be found. We recommend you +download the latest egg from our `download site +<http://sourceforge.net/projects/matplotlib/files/>`_ directly to your +harddrive, and manually install it with + + > easy_install --install-dir=~/dev/lib/python2.5/site-packages/ matplotlib-0.99.0.rc1-py2.5-macosx-10.5-i386.egg + + Some users have reported problems with the egg for 0.98 from the matplotlib download site, with ``easy_install``, getting an error:: Modified: trunk/matplotlib/doc/pyplots/plotmap.py =================================================================== --- trunk/matplotlib/doc/pyplots/plotmap.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/pyplots/plotmap.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -5,7 +5,9 @@ # the data is interpolated to the native projection grid. import os from mpl_toolkits.basemap import Basemap, shiftgrid -from pylab import title, colorbar, show, axes, cm, load, arange, figure, \ +import numpy as np + +from pylab import title, colorbar, show, axes, cm, arange, figure, \ text # read in topo data (on a regular lat/lon grid) @@ -15,9 +17,9 @@ if not os.path.exists(datadir): raise SystemExit('You need to download the data with svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/htdocs/screenshots/data/" and set the datadir variable in %s'%__file__) -topoin = load(os.path.join(datadir, 'etopo20data.gz')) -lons = load(os.path.join(datadir, 'etopo20lons.gz')) -lats = load(os.path.join(datadir, 'etopo20lats.gz')) +topoin = np.loadtxt(os.path.join(datadir, 'etopo20data.gz')) +lons = np.loadtxt(os.path.join(datadir, 'etopo20lons.gz')) +lats = np.loadtxt(os.path.join(datadir, 'etopo20lats.gz')) # shift data so lons go from -180 to 180 instead of 20 to 380. topoin,lons = shiftgrid(180.,topoin,lons,start=False) Modified: trunk/matplotlib/doc/users/installing.rst =================================================================== --- trunk/matplotlib/doc/users/installing.rst 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/doc/users/installing.rst 2009-08-04 13:20:29 UTC (rev 7346) @@ -63,14 +63,17 @@ And a *voila*, a figure pops up. But we are putting the cart ahead of the horse -- first we need to get matplotlib installed. We provide prebuilt binaries for OS X and Windows on the matplotlib `download -<http://sourceforge.net/project/showfiles.php?group_id=80706>`_ page. -Click on the latest release of the "matplotlib" package, choose your -python version (2.4 or 2.5) and your platform (macosx or win32) and -you should be good to go. If you have any problems, please check the +<http://sourceforge.net/projects/matplotlib/files/>`_ page. Click on +the latest release of the "matplotlib" package, choose your python +version (2.4 or 2.5) and your platform (macosx or win32) and you +should be good to go. If you have any problems, please check the :ref:`installing-faq`, google around a little bit, and post a question the `mailing list <http://sourceforge.net/project/showfiles.php?group_id=80706>`_. +Instructions for installing our OSX binaries are found in the FAQ +ref:`install_osx_binaries`. + Note that when testing matplotlib installations from the interactive python console, there are some issues relating to user interface toolkits and interactive settings that are discussed in @@ -114,7 +117,8 @@ These are external packages which you will need to install before installing matplotlib. Windows users only need the first two (python and numpy) since the others are built into the matplotlib windows -installers available for download at the sourceforge site. +installers available for download at the sourceforge site. If you are +building on OSX, see :ref:`build_osx` :term:`python` 2.4 (or later but not python3) matplotlib requires python 2.4 or later (`download <http://www.python.org/download/>`__) @@ -183,3 +187,19 @@ +.. _build_osx: + +Building on OSX +================== + +The build situation on OSX is complicated by the various places one +can get the png and freetype requirements from (darwinports, fink, +/usr/X11R6) and the different architectures (x86, ppc, universal) and +the different OSX version (10.4 and 10.5). We recommend that you build +the way we do for the OSX release: by grabbing the tarbar or svn +repository, cd-ing into the release/osx dir, and following the +instruction in the README. This directory has a Makefile which will +automatically grab the zlib, png and freetype dependencies from the +web, build them with the right flags to make universal libraries, and +then build the matplotlib source and binary installers. + \ No newline at end of file Copied: trunk/matplotlib/examples/pylab_examples/barchart_demo2.py (from rev 7337, branches/v0_99_maint/examples/pylab_examples/barchart_demo2.py) =================================================================== --- trunk/matplotlib/examples/pylab_examples/barchart_demo2.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/barchart_demo2.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -0,0 +1,107 @@ +""" +Thanks Josh Hemann for the example + +This examples comes from an application in which grade school gym +teachers wanted to be able to show parents how their child did across +a handful of fitness tests, and importantly, relative to how other +children did. To extract the plotting code for demo purposes, we'll +just make up some data for little Johnny Doe... + +""" +import numpy as np +import matplotlib.pyplot as plt +import pylab +from matplotlib.patches import Polygon +from matplotlib.ticker import MaxNLocator + + + +student = 'Johnny Doe' +grade = 2 +gender = 'boy' +cohortSize = 62 #The number of other 2nd grade boys + +numTests = 5 +testNames = ['Pacer Test', 'Flexed Arm\n Hang', 'Mile Run', 'Agility', + 'Push Ups'] +testMeta = ['laps', 'sec', 'min:sec', 'sec', ''] +scores = ['7', '48', '12:52', '17', '14'] +rankings = np.round(np.random.uniform(0, 1, numTests)*100, 0) + +fig = plt.figure(figsize=(9,7)) +ax1 = fig.add_subplot(111) +plt.subplots_adjust(left=0.115, right=0.88) +fig.canvas.set_window_title('Eldorado K-8 Fitness Chart') +pos = np.arange(numTests)+0.5 #Center bars on the Y-axis ticks +rects = ax1.barh(pos, rankings, align='center', height=0.5, color='m') + +ax1.axis([0,100,0,5]) +pylab.yticks(pos, testNames) +ax1.set_title('Johnny Doe') +plt.text(50, -0.5, 'Cohort Size: ' + str(cohortSize), + horizontalalignment='center', size='small') + +# Set the right-hand Y-axis ticks and labels and set X-axis tick marks at the +# deciles +ax2 = ax1.twinx() +ax2.plot([100,100], [0, 5], 'white', alpha=0.1) +ax2.xaxis.set_major_locator(MaxNLocator(11)) +xticks = pylab.setp(ax2, xticklabels=['0','10','20','30','40','50','60', +'70', + '80','90','100']) +ax2.xaxis.grid(True, linestyle='--', which='major', color='grey', +alpha=0.25) +#Plot a solid vertical gridline to highlight the median position +plt.plot([50,50], [0, 5], 'grey', alpha=0.25) + +# Build up the score labels for the right Y-axis by first appending a carriage +# return to each string and then tacking on the appropriate meta information +# (i.e., 'laps' vs 'seconds'). We want the labels centered on the ticks, so if +# there is no meta info (like for pushups) then don't add the carriage return to +# the string + +def withnew(i, scr): + if testMeta[i] != '' : return '%s\n'%scr + else: return scr +scoreLabels = [withnew(i, scr) for i,scr in enumerate(scores)] +scoreLabels = [i+j for i,j in zip(scoreLabels, testMeta)] +pylab.yticks(pos, scoreLabels) +ax2.set_ylabel('Test Scores') +#Make list of numerical suffixes corresponding to position in a list +# 0 1 2 3 4 5 6 7 8 9 +suffixes =['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th'] +ax2.set_xlabel('Percentile Ranking Across ' + str(grade) + suffixes[grade] \ + + ' Grade ' + gender.title() + 's') + +# Lastly, write in the ranking inside each bar to aid in interpretation +for rect in rects: + # Rectangle widths are already integer-valued but are floating + # type, so it helps to remove the trailing decimal point and 0 by + # converting width to int type + width = int(rect.get_width()) + + # Figure out what the last digit (width modulo 10) so we can add + # the appropriate numerical suffix (e.g. 1st, 2nd, 3rd, etc) + lastDigit = width % 10 + # Note that 11, 12, and 13 are special cases + if (width == 11) or (width == 12) or (width == 13): + suffix = 'th' + else: + suffix = suffixes[lastDigit] + + rankStr = str(width) + suffix + if (width < 5): # The bars aren't wide enough to print the ranking inside + xloc = width + 1 # Shift the text to the right side of the right edge + clr = 'black' # Black against white background + align = 'left' + else: + xloc = 0.98*width # Shift the text to the left side of the right edge + clr = 'white' # White on magenta + align = 'right' + + yloc = rect.get_y()+rect.get_height()/2.0 #Center the text vertically in the bar + ax1.text(xloc, yloc, rankStr, horizontalalignment=align, + verticalalignment='center', color=clr, weight='bold') + +plt.show() + Copied: trunk/matplotlib/examples/pylab_examples/boxplot_demo2.py (from rev 7337, branches/v0_99_maint/examples/pylab_examples/boxplot_demo2.py) =================================================================== --- trunk/matplotlib/examples/pylab_examples/boxplot_demo2.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/boxplot_demo2.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -0,0 +1,121 @@ +""" +Thanks Josh Hemann for the example +""" + +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.patches import Polygon + + +# Generate some data from five different probability distributions, +# each with different characteristics. We want to play with how an IID +# bootstrap resample of the data preserves the distributional +# properties of the original sample, and a boxplot is one visual tool +# to make this assessment +numDists = 5 +randomDists = ['Normal(1,1)',' Lognormal(1,1)', 'Exp(1)', 'Gumbel(6,4)', + 'Triangular(2,9,11)'] +N = 500 +norm = np.random.normal(1,1, N) +logn = np.random.lognormal(1,1, N) +expo = np.random.exponential(1, N) +gumb = np.random.gumbel(6, 4, N) +tria = np.random.triangular(2, 9, 11, N) + +# Generate some random indices that we'll use to resample the original data +# arrays. For code brevity, just use the same random indices for each array +bootstrapIndices = np.random.random_integers(0, N-1, N) +normBoot = norm[bootstrapIndices] +expoBoot = expo[bootstrapIndices] +gumbBoot = gumb[bootstrapIndices] +lognBoot = logn[bootstrapIndices] +triaBoot = tria[bootstrapIndices] + +data = [norm, normBoot, logn, lognBoot, expo, expoBoot, gumb, gumbBoot, + tria, triaBoot] + +fig = plt.figure(figsize=(10,6)) +fig.canvas.set_window_title('A Boxplot Example') +ax1 = fig.add_subplot(111) +plt.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25) + +bp = plt.boxplot(data, notch=0, sym='+', vert=1, whis=1.5) +plt.setp(bp['boxes'], color='black') +plt.setp(bp['whiskers'], color='black') +plt.setp(bp['fliers'], color='red', marker='+') + +# Add a horizontal grid to the plot, but make it very light in color +# so we can use it for reading data values but not be distracting +ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', + alpha=0.5) + +# Hide these grid behind plot objects +ax1.set_axisbelow(True) +ax1.set_title('Comparison of IID Bootstrap Resampling Across Five Distributions') +ax1.set_xlabel('Distribution') +ax1.set_ylabel('Value') + +# Now fill the boxes with desired colors +boxColors = ['darkkhaki','royalblue'] +numBoxes = numDists*2 +medians = range(numBoxes) +for i in range(numBoxes): + box = bp['boxes'][i] + boxX = [] + boxY = [] + for j in range(5): + boxX.append(box.get_xdata()[j]) + boxY.append(box.get_ydata()[j]) + boxCoords = zip(boxX,boxY) + # Alternate between Dark Khaki and Royal Blue + k = i % 2 + boxPolygon = Polygon(boxCoords, facecolor=boxColors[k]) + ax1.add_patch(boxPolygon) + # Now draw the median lines back over what we just filled in + med = bp['medians'][i] + medianX = [] + medianY = [] + for j in range(2): + medianX.append(med.get_xdata()[j]) + medianY.append(med.get_ydata()[j]) + plt.plot(medianX, medianY, 'k') + medians[i] = medianY[0] + # Finally, overplot the sample averages, with horixzontal alignment + # in the center of each box + plt.plot([np.average(med.get_xdata())], [np.average(data[i])], + color='w', marker='*', markeredgecolor='k') + +# Set the axes ranges and axes labels +ax1.set_xlim(0.5, numBoxes+0.5) +top = 40 +bottom = -5 +ax1.set_ylim(bottom, top) +xtickNames = plt.setp(ax1, xticklabels=np.repeat(randomDists, 2)) +plt.setp(xtickNames, rotation=45, fontsize=8) + +# Due to the Y-axis scale being different across samples, it can be +# hard to compare differences in medians across the samples. Add upper +# X-axis tick labels with the sample medians to aid in comparison +# (just use two decimal places of precision) +pos = np.arange(numBoxes)+1 +upperLabels = [str(np.round(s, 2)) for s in medians] +weights = ['bold', 'semibold'] +for tick,label in zip(range(numBoxes),ax1.get_xticklabels()): + k = tick % 2 + ax1.text(pos[tick], top-(top*0.05), upperLabels[tick], + horizontalalignment='center', size='x-small', weight=weights[k], + color=boxColors[k]) + +# Finally, add a basic legend +plt.figtext(0.80, 0.08, str(N) + ' Random Numbers' , + backgroundcolor=boxColors[0], color='black', weight='roman', + size='x-small') +plt.figtext(0.80, 0.045, 'IID Bootstrap Resample', +backgroundcolor=boxColors[1], + color='white', weight='roman', size='x-small') +plt.figtext(0.80, 0.015, '*', color='white', backgroundcolor='silver', + weight='roman', size='medium') +plt.figtext(0.815, 0.013, ' Average Value', color='black', weight='roman', + size='x-small') + +plt.show() Modified: trunk/matplotlib/examples/pylab_examples/load_converter.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/load_converter.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/examples/pylab_examples/load_converter.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -1,8 +1,9 @@ from matplotlib.dates import strpdate2num -from matplotlib.mlab import load +#from matplotlib.mlab import load +import numpy as np from pylab import figure, show -dates, closes = load( +dates, closes = np.loadtxt( '../data/msft.csv', delimiter=',', converters={0:strpdate2num('%d-%b-%y')}, skiprows=1, usecols=(0,2), unpack=True) Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/examples/tests/backend_driver.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -373,7 +373,7 @@ if backend in rcsetup.interactive_bk: tmpfile.write('show()') else: - tmpfile.write('\nsavefig("%s", dpi=150)' % outfile) + tmpfile.write('\nsavefig(r"%s", dpi=150)' % outfile) tmpfile.close() start_time = time.time() @@ -457,7 +457,7 @@ python = ['valgrind', '--tool=memcheck', '--leak-check=yes', '--log-file=%(name)s', 'python'] elif sys.platform == 'win32': - python = [r'c:\Python24\python.exe'] + python = [sys.executable] else: python = ['python'] Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -4229,20 +4229,20 @@ # FIXME: convert the following to proper input validation # raising ValueError; don't use assert for this. - assert len(left)==nbars, "argument 'left' must be %d or scalar" % nbars - assert len(height)==nbars, ("argument 'height' must be %d or scalar" % + assert len(left)==nbars, "incompatible sizes: argument 'left' must be length %d or scalar" % nbars + assert len(height)==nbars, ("incompatible sizes: argument 'height' must be length %d or scalar" % nbars) - assert len(width)==nbars, ("argument 'width' must be %d or scalar" % + assert len(width)==nbars, ("incompatible sizes: argument 'width' must be length %d or scalar" % nbars) - assert len(bottom)==nbars, ("argument 'bottom' must be %d or scalar" % + assert len(bottom)==nbars, ("incompatible sizes: argument 'bottom' must be length %d or scalar" % nbars) if yerr is not None and len(yerr)!=nbars: raise ValueError( - "bar() argument 'yerr' must be len(%s) or scalar" % nbars) + "incompatible sizes: bar() argument 'yerr' must be len(%s) or scalar" % nbars) if xerr is not None and len(xerr)!=nbars: raise ValueError( - "bar() argument 'xerr' must be len(%s) or scalar" % nbars) + "incompatible sizes: bar() argument 'xerr' must be len(%s) or scalar" % nbars) patches = [] Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -772,6 +772,11 @@ bind(self, wx.EVT_LEAVE_WINDOW, self._onLeave) bind(self, wx.EVT_ENTER_WINDOW, self._onEnter) bind(self, wx.EVT_IDLE, self._onIdle) + #Add middle button events + bind(self, wx.EVT_MIDDLE_DOWN, self._onMiddleButtonDown) + bind(self, wx.EVT_MIDDLE_DCLICK, self._onMiddleButtonDown) + bind(self, wx.EVT_MIDDLE_UP, self._onMiddleButtonUp) + self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) self.macros = {} # dict from wx id to seq of macros @@ -1183,6 +1188,7 @@ # so no need to do anything here except to make sure # the whole background is repainted. self.Refresh(eraseBackground=False) + FigureCanvasBase.resize_event(self) def _get_key(self, evt): @@ -1251,6 +1257,24 @@ if self.HasCapture(): self.ReleaseMouse() FigureCanvasBase.button_release_event(self, x, y, 1, guiEvent=evt) + #Add middle button events + def _onMiddleButtonDown(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self.CaptureMouse() + FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt) + + def _onMiddleButtonUp(self, evt): + """End measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + #print 'release button', 1 + evt.Skip() + if self.HasCapture(): self.ReleaseMouse() + FigureCanvasBase.button_release_event(self, x, y, 2, guiEvent=evt) + def _onMouseWheel(self, evt): """Translate mouse wheel events into matplotlib events""" Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -2595,7 +2595,7 @@ for i, name in enumerate(r.dtype.names): funcs.append(with_mask(csvformat_factory(formatd[name]).tostr)) - fh, opened = cbook.to_filehandle(fname, 'w', return_opened=True) + fh, opened = cbook.to_filehandle(fname, 'wb', return_opened=True) writer = csv.writer(fh, delimiter=delimiter) header = r.dtype.names if withheader: Modified: trunk/matplotlib/lib/matplotlib/texmanager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/texmanager.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/lib/matplotlib/texmanager.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -56,7 +56,7 @@ def dvipng_hack_alpha(): p = Popen('dvipng -version', shell=True, stdin=PIPE, stdout=PIPE, - stderr=STDOUT, close_fds=True) + stderr=STDOUT, close_fds=(sys.platform!='win32')) stdin, stdout = p.stdin, p.stdout for line in stdout: if line.startswith('dvipng '): Modified: trunk/matplotlib/release/osx/Makefile =================================================================== --- trunk/matplotlib/release/osx/Makefile 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/release/osx/Makefile 2009-08-04 13:20:29 UTC (rev 7346) @@ -1,3 +1,5 @@ +PYVERSION=2.6 +PYTHON=python${PYVERSION} SRCDIR=${PWD} ZLIBVERSION=1.2.3 PNGVERSION=1.2.33 @@ -2,3 +4,4 @@ FREETYPEVERSION=2.3.7 -MPLVERSION=0.98.5.3 +MPLVERSION=0.99.0.rc1 +BDISTMPKGVERSION=0.4.4 MPLSRC=matplotlib-${MPLVERSION} @@ -20,8 +23,8 @@ clean: rm -rf zlib-${ZLIBVERSION}.tar.gz libpng-${PNGVERSION}.tar.bz2 \ - freetype-${FREETYPEVERSION}.tar.bz2 bdist_mpkg-0.4.3.tar.gz \ - bdist_mpkg-0.4.3 \ + freetype-${FREETYPEVERSION}.tar.bz2 bdist_mpkg-${BDISTMPKGVERSION}.tar.gz \ + bdist_mpkg-${BDISTMPKGVERSION} \ zlib-${ZLIBVERSION} libpng-${PNGVERSION} freetype-${FREETYPEVERSION} \ matplotlib-${MPLVERSION} *~ @@ -29,10 +32,9 @@ wget http://www.zlib.net/zlib-${ZLIBVERSION}.tar.gz &&\ wget http://internap.dl.sourceforge.net/sourceforge/libpng/libpng-${PNGVERSION}.tar.bz2 &&\ wget http://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPEVERSION}.tar.bz2&&\ - wget http://pypi.python.org/packages/source/b/bdist_mpkg/bdist_mpkg-0.4.3.tar.gz&&\ - tar xvfz bdist_mpkg-0.4.3.tar.gz &&\ - patch -p0 < data/bdist.patch - echo "You need to to install bdist_mpkg-0.4.3 now" + wget http://pypi.python.org/packages/source/b/bdist_mpkg/bdist_mpkg-${BDISTMPKGVERSION}.tar.gz&&\ + tar xvfz bdist_mpkg-${BDISTMPKGVERSION}.tar.gz &&\ + echo "You need to to install bdist_mpkg-${BDISTMPKGVERSION} now" @@ -87,16 +89,16 @@ export CFLAGS=${CFLAGS} &&\ export LDFLAGS=${LDFLAGS} &&\ bdist_mpkg &&\ - python setupegg.py bdist_egg &&\ + ${PYTHON} setupegg.py bdist_egg &&\ cd dist && \ - zip -ro matplotlib-${MPLVERSION}-py2.5-macosx10.5.zip matplotlib-${MPLVERSION}-py2.5-macosx10.5.mpkg + zip -ro matplotlib-${MPLVERSION}-py${PYVERSION}-macosx10.5_mpkg.zip matplotlib-${MPLVERSION}-py${PYVERSION}-macosx10.5.mpkg upload: rm -rf upload &&\ mkdir upload &&\ cp matplotlib-${MPLVERSION}.tar.gz upload/ &&\ - cp matplotlib-${MPLVERSION}/dist/matplotlib-${MPLVERSION}_r0-py2.5-macosx-10.3-fat.egg upload/matplotlib-${MPLVERSION}-macosx-py2.5.egg &&\ - cp matplotlib-${MPLVERSION}/dist/matplotlib-${MPLVERSION}-py2.5-macosx10.5.zip upload/matplotlib-${MPLVERSION}-py2.5-mpkg.zip&&\ + cp matplotlib-${MPLVERSION}/dist/matplotlib-${MPLVERSION}_r0-py${PYVERSION}-macosx-10.3-fat.egg upload/matplotlib-${MPLVERSION}-macosx-py${PYVERSION}.egg &&\ + cp matplotlib-${MPLVERSION}/dist/matplotlib-${MPLVERSION}-py${PYVERSION}-macosx10.5.zip upload/matplotlib-${MPLVERSION}-py${PYVERSION}-mpkg.zip&&\ scp upload/* jd...@fr...:uploads/ all: Modified: trunk/matplotlib/release/osx/README.txt =================================================================== --- trunk/matplotlib/release/osx/README.txt 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/release/osx/README.txt 2009-08-04 13:20:29 UTC (rev 7346) @@ -7,9 +7,7 @@ ------------- * :file:`bdist_mkpg` - the distutils.extension to build Installer.app - mpkg installers. It is patched from the tarball with - file:`data/bdist.patch` because 0.4.3 is broken on OS X 10.5. - Instructions on how to patch and install are below + mpkg installers. * :file:`data` - some config files and patches needed for the build @@ -21,6 +19,16 @@ How to build -------------- +* You need a python framework build , numpy and wxpython to build the + mpl installers (wx requires this and we need wx to build the wxagg + extension). You can get the three required dependencies as + Installer apps, eg: + + + http://www.python.org/ftp/python/2.6.2/python-2.6.2-macosx2009-04-16.dmg + http://downloads.sourceforge.net/project/numpy/NumPy/1.3.0/numpy-1.3.0-py2.6-macosx10.5.dmg?use_mirror=voxel + http://downloads.sourceforge.net/project/wxpython/wxPython/2.8.10.1/wxPython2.8-osx-unicode-2.8.10.1-universal-py2.6.dmg?use_mirror=voxel + * You need to make sure to unset PKG_CONFIG_PATH to make sure the static linking below is respected. Otherwise the mpl build script will dynamically link using the libs from pkgconfig if you have this @@ -38,7 +46,7 @@ * install the patched bdist_mpkg, that the fetch_deps step just created:: - cd bdist_mpkg-0.4.3 + cd bdist_mpkg-0.4.4 sudo python setup.py install * build the dependencies:: @@ -64,7 +72,7 @@ cd release/osx/ unset PKG_CONFIG_PATH make fetch_deps - cd bdist_mpkg-0.4.3 + cd bdist_mpkg-0.4.4 sudo python setup.py install cd .. make dependencies Modified: trunk/matplotlib/release/win32/Makefile =================================================================== --- trunk/matplotlib/release/win32/Makefile 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/release/win32/Makefile 2009-08-04 13:20:29 UTC (rev 7346) @@ -1,4 +1,4 @@ -PYDIR = C:/Python26 +PYDIR = C:/Python25 PYTHON = ${PYDIR}/python.exe SRCDIR = ${PWD} WINSRCDIR = `${PWD}/data/mingw_path.sh ${PWD}` @@ -6,7 +6,7 @@ PNGVERSION = 1.2.36 FREETYPEVERSION = 2.3.9 TCLTKVERSION = 8.5.7 -MPLVERSION = 0.98.5.3 +MPLVERSION = 0.99.0.rc1 ## You shouldn't need to configure past this point @@ -89,8 +89,8 @@ rm -rf build &&\ cp ../data/setup*.* . &&\ export CFLAGS="${CFLAGS}" &&\ - ${PYTHON} setupwin.py build_ext -c mingw32 -I ${PY_INCLUDE} -L ${PY_LINKER} bdist_wininst - #${PYTHON} setupwinegg.py build_ext -c mingw32 -I ${PY_INCLUDE} -L ${PY_LINKER} bdist_egg + ${PYTHON} setupwin.py build_ext -c mingw32 -I ${PY_INCLUDE} -L ${PY_LINKER} bdist_wininst &&\ + ${PYTHON} setupwinegg.py build_ext -c mingw32 -I ${PY_INCLUDE} -L ${PY_LINKER} bdist_egg inplace: Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/setupext.py 2009-08-04 13:20:29 UTC (rev 7346) @@ -51,7 +51,7 @@ 'linux' : ['/usr/local', '/usr',], 'cygwin' : ['/usr/local', '/usr',], 'darwin' : ['/sw/lib/freetype2', '/sw/lib/freetype219', '/usr/local', - '/usr', '/sw', '/usr/X11R6'], + '/usr', '/sw'], 'freebsd4' : ['/usr/local', '/usr'], 'freebsd5' : ['/usr/local', '/usr'], 'freebsd6' : ['/usr/local', '/usr'], @@ -174,7 +174,7 @@ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - close_fds=True) + close_fds=(sys.platform != 'win32')) return p.stdin, p.stdout class CleanUpFile: @@ -458,7 +458,7 @@ try: stdin, stdout = run_child_process('latex -version') line = stdout.readlines()[0] - pattern = '3\.1\d+' + pattern = '(3\.1\d+)|(MiKTeX \d+.\d+)' match = re.search(pattern, line) print_status("latex", match.group(0)) return True Modified: trunk/matplotlib/src/_macosx.m =================================================================== --- trunk/matplotlib/src/_macosx.m 2009-08-04 13:15:14 UTC (rev 7345) +++ trunk/matplotlib/src/_macosx.m 2009-08-04 13:20:29 UTC (rev 7346) @@ -7,15 +7,19 @@ static int nwin = 0; /* The number of open windows */ + +/* Use Atsui for Mac OS X 10.4, CoreText for Mac OS X 10.5 */ +#ifndef MAC_OS_X_VERSION_10_5 static int ngc = 0; /* The number of graphics contexts in use */ /* For drawing Unicode strings with ATSUI */ static ATSUStyle style = NULL; static ATSUTextLayout layout = NULL; +#endif /* CGFloat was defined in Mac OS X 10.5 */ -#ifndef CGFloat +#ifndef CGFLOAT_DEFINED #define CGFloat float #endif @@ -171,6 +175,7 @@ return 1; } +#ifndef MAC_OS_X_VERSION_10_5 static int _init_atsui(void) { OSStatus status; @@ -208,6 +213,7 @@ if (status!=noErr) PyErr_WarnEx(PyExc_RuntimeWarning, "ATSUDisposeTextLayout failed", 1); } +#endif static int _draw_path(CGContextRef cr, void* iterator) { @@ -336,6 +342,10 @@ - (void)mouseUp:(NSEvent*)event; - (void)mouseDragged:(NSEvent*)event; - (void)mouseMoved:(NSEvent*)event; +- (void)rightMouseDown:(NSEvent*)event; +- (void)rightMouseUp:(NSEvent*)event; +- (void)otherMouseDown:(NSEvent*)event; +- (void)otherMouseUp:(NSEvent*)event; - (void)setRubberband:(NSRect)rect; - (void)removeRubberband; - (const char*)convertKeyEvent:(NSEvent*)event; @@ -375,6 +385,7 @@ CGContextRef cr; NSSize size; int level; + CGFloat color[4]; } GraphicsContext; static CGMutablePathRef _create_path(void* iterator) @@ -440,6 +451,7 @@ self->cr = NULL; self->level = 0; +#ifndef MAC_OS_X_VERSION_10_5 if (ngc==0) { int ok = _init_atsui(); @@ -449,10 +461,12 @@ } } ngc++; +#endif return (PyObject*) self; } +#ifndef MAC_OS_X_VERSION_10_5 static void GraphicsContext_dealloc(GraphicsContext *self) { @@ -461,6 +475,7 @@ self->ob_type->tp_free((PyObject*)self); } +#endif static PyObject* GraphicsContext_repr(GraphicsContext* self) @@ -516,6 +531,9 @@ return NULL; } CGContextSetAlpha(cr, alpha); + + self->color[3] = alpha; + Py_INCREF(Py_None); return Py_None; } @@ -651,7 +669,7 @@ static BOOL _set_dashes(CGContextRef cr, PyObject* linestyle) { - float phase = 0.0; + CGFloat phase = 0.0; PyObject* offset; PyObject* dashes; @@ -686,7 +704,7 @@ } int n = PyTuple_GET_SIZE(dashes); int i; - float* lengths = malloc(n*sizeof(float)); + CGFloat* lengths = malloc(n*sizeof(CGFloat)); if(!lengths) { PyErr_SetString(PyExc_MemoryError, "Failed to store dashes"); @@ -697,9 +715,9 @@ { PyObject* value = PyTuple_GET_ITEM(dashes, i); if (PyFloat_Check(value)) - lengths[i] = (float) PyFloat_AS_DOUBLE(value); + lengths[i] = (CGFloat) PyFloat_AS_DOUBLE(value); else if (PyInt_Check(value)) - lengths[i] = (float) PyInt_AS_LONG(value); + lengths[i] = (CGFloat) PyInt_AS_LONG(value); else break; } Py_DECREF(dashes); @@ -750,6 +768,11 @@ CGContextSetRGBStrokeColor(cr, r, g, b, 1.0); CGContextSetRGBFillColor(cr, r, g, b, 1.0); + + self->color[0] = r; + self->color[1] = g; + self->color[2] = b; + Py_INCREF(Py_None); return Py_None; } @@ -889,28 +912,12 @@ } else { - int ok; - float color[4] = {0, 0, 0, 1}; CGPatternRef pattern; CGColorSpaceRef baseSpace; CGColorSpaceRef patternSpace; static const CGPatternCallbacks callbacks = {0, &_draw_hatch, &_release_hatch}; - PyObject* rgb = PyObject_CallMethod((PyObject*)self, "get_rgb", ""); - if (!rgb) - { - Py_DECREF(hatchpath); - return NULL; - } - ok = PyArg_ParseTuple(rgb, "ffff", &color[0], &color[1], &color[2], &color[3]); - Py_DECREF(rgb); - if (!ok) - { - Py_DECREF(hatchpath); - return NULL; - } - baseSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); if (!baseSpace) { @@ -938,7 +945,7 @@ kCGPatternTilingNoDistortion, false, &callbacks); - CGContextSetFillPattern(cr, pattern, color); + CGContextSetFillPattern(cr, pattern, self->color); CGPatternRelease(pattern); iterator = get_path_iterator(path, transform, @@ -1227,6 +1234,8 @@ if (Ntransforms) { + CGAffineTransform master; + double a, b, c, d, tx, ty; PyObject* values = PyObject_CallMethod(master_transform, "to_values", ""); if (!values) { @@ -1239,15 +1248,15 @@ ok = 0; goto exit; } - CGAffineTransform master; - ok = PyArg_ParseTuple(values, "ffffff", - &master.a, - &master.b, - &master.c, - &master.d, - &master.tx, - &master.ty); + /* CGAffineTransform contains CGFloat; cannot use master directly */ + ok = PyArg_ParseTuple(values, "dddddd", &a, &b, &c, &d, &tx, &ty); Py_DECREF(values); + master.a = a; + master.b = b; + master.c = c; + master.d = d; + master.tx = tx; + master.ty = ty; if (!ok) goto exit; CGContextConcatCTM(cr, master); } @@ -1652,13 +1661,15 @@ } if (PyTuple_Check(values)) { - ok = PyArg_ParseTuple(values, "ffffff", - &master.a, - &master.b, - &master.c, - &master.d, - &master.tx, - &master.ty); + double a, b, c, d, tx, ty; + /* CGAffineTransform contains CGFloat; cannot use master directly */ + ok = PyArg_ParseTuple(values, "dddddd", &a, &b, &c, &d, &tx, &ty); + master.a = a; + master.b = b; + master.c = c; + master.d = d; + master.tx = tx; + master.ty = ty; } else { @@ -1866,7 +1877,11 @@ } +#ifdef MAC_OS_X_VERSION_10_5 +static CTFontRef +#else static ATSFontRef +#endif setfont(CGContextRef cr, PyObject* family, float size, const char weight[], const char italic[]) { @@ -1876,7 +1891,11 @@ const char* temp; const char* name = "Times-Roman"; CFStringRef string; - ATSFontRef atsfont = 0; +#ifdef MAC_OS_X_VERSION_10_5 + CTFontRef font = 0; +#else + ATSFontRef font = 0; +#endif const int k = (strcmp(italic, "italic") ? 0 : 2) + (strcmp(weight, "bold") ? 0 : 1); @@ -2072,26 +2091,38 @@ string = CFStringCreateWithCString(kCFAllocatorDefault, temp, kCFStringEncodingMacRoman); - atsfont = ATSFontFindFromPostScriptName(string, kATSOptionFlagsDefault); +#ifdef MAC_OS_X_VERSION_10_5 + font = CTFontCreateWithName(string, size, NULL); +#else + font = ATSFontFindFromPostScriptName(string, kATSOptionFlagsDefault); +#endif + CFRelease(string); - if(atsfont) + if(font) { name = temp; break; } } - if(!atsfont) + if(!font) { string = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman); - atsfont = ATSFontFindFromPostScriptName(string, kATSOptionFlagsDefault); +#ifdef MAC_OS_X_VERSION_10_5 + font = CTFontCreateWithName(string, size, NULL); +#else + font = ATSFontFindFromPostScriptName(string, kATSOptionFlagsDefault); +#endif CFRelease(string); } +#ifndef MAC_OS_X_VERSION_10_5 CGContextSelectFont(cr, name, size, kCGEncodingMacRoman); - return atsfont; +#endif + return font; } +#ifdef MAC_OS_X_VERSION_10_5 static PyObject* GraphicsContext_draw_text (GraphicsContext* self, PyObject* args) { @@ -2104,6 +2135,174 @@ const char* weight; const char* italic; float angle; + CTFontRef font; + CGColorRef color; + CGFloat descent; + + CFStringRef keys[2]; + CFTypeRef values[2]; + + CGContextRef cr = self->cr; + if (!cr) + { + PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL"); + return NULL; + } + + if(!PyArg_ParseTuple(args, "ffu#Ofssf", + &x, + &y, + &text, + &n, + &family, + &size, + &weight, + &italic, + &angle)) return NULL; + + font = setfont(cr, family, size, weight, italic); + + color = CGColorCreateGenericRGB(self->color[0], + self->color[1], + self->color[2], + self->color[3]); + + keys[0] = kCTFontAttributeName; + keys[1] = kCTForegroundColorAttributeName; + values[0] = font; + values[1] = color; + CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, + (const void**)&keys, + (const void**)&values, + 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CGColorRelease(color); + CFRelease(font); + + CFStringRef s = CFStringCreateWithCharacters(kCFAllocatorDefault, text, n); + + CFAttributedStringRef string = CFAttributedStringCreate(kCFAllocatorDefault, + s, + attributes); + CFRelease(s); + CFRelease(attributes); + + CTLineRef line = CTLineCreateWithAttributedString(string); + CFRelease(string); + + CTLineGetTypographicBounds(line, NULL, &descent, NULL); + + if (!line) + { + PyErr_SetString(PyExc_RuntimeError, + "CTLineCreateWithAttributedString failed"); + return NULL; + } + + CGContextSetTextMatrix(cr, CGAffineTransformIdentity); + if (angle) + { + CGContextSaveGState(cr); + CGContextTranslateCTM(cr, x, y); + CGContextRotateCTM(cr, angle*M_PI/180); + CTLineDraw(line, cr); + CGContextRestoreGState(cr); + } + else + { + CGContextSetTextPosition(cr, x, y); + CTLineDraw(line, cr); + } + CFRelease(line); + + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* +GraphicsContext_get_text_width_height_descent(GraphicsContext* self, PyObject* args) +{ + const UniChar* text; + int n; + PyObject* family; + float size; + const char* weight; + const char* italic; + + CGFloat ascent; + CGFloat descent; + double width; + CGRect rect; + + CTFontRef font; + + CGContextRef cr = self->cr; + if (!cr) + { + PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL"); + return NULL; + } + + if(!PyArg_ParseTuple(args, "u#Ofss", + &text, &n, &family, &size, &weight, &italic)) + return NULL; + + font = setfont(cr, family, size, weight, italic); + + CFStringRef keys[1]; + CFTypeRef values[1]; + + keys[0] = kCTFontAttributeName; + values[0] = font; + CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, + (const void**)&keys, + (const void**)&values, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(font); + + CFStringRef s = CFStringCreateWithCharacters(kCFAllocatorDefault, text, n); + + CFAttributedStringRef string = CFAttributedStringCreate(kCFAllocatorDefault, + s, + attributes); + CFRelease(s); + CFRelease(attributes); + + CTLineRef line = CTLineCreateWithAttributedString(string); + CFRelease(string); + + if (!line) + { + PyErr_SetString(PyExc_RuntimeError, + "CTLineCreateWithAttributedString failed"); + return NULL; + } + + width = CTLineGetTypographicBounds(line, &ascent, &descent, NULL); + rect = CTLineGetImageBounds(line, cr); + + CFRelease(line); + + return Py_BuildValue("fff", width, rect.size.height, descent); +} + +#else + +static PyObject* +GraphicsContext_draw_text (GraphicsContext* self, PyObject* args) +{ + float x; + float y; + const UniChar* text; + int n; + PyObject* family; + float size; + const char* weight; + const char* italic; + float angle; ATSFontRef atsfont; CGContextRef cr = self->cr; if (!cr) @@ -2188,6 +2387,102 @@ return Py_None; } +static PyObject* +GraphicsContext_get_text_width_height_descent(GraphicsContext* self, PyObject* args) +{ + const UniChar* text; + int n; + PyObject* family; + float size; + const char* weight; + const char* italic; + + ATSFontRef atsfont; + + CGContextRef cr = self->cr; + if (!cr) + { + PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL"); + return NULL; + } + + if(!PyArg_ParseTuple(args, "u#Ofss", &text, &n, &family, &size, &weight, &italic)) return NULL; + + atsfont = setfont(cr, family, size, weight, italic); + + OSStatus status = noErr; + ATSUAttributeTag tags[] = {kATSUFontTag, + kATSUSizeTag, + kATSUQDBoldfaceTag, + kATSUQDItalicTag}; + ByteCount sizes[] = {sizeof(ATSUFontID), + sizeof(Fixed), + sizeof(Boolean), + sizeof(Boolean)}; + Fixed atsuSize = Long2Fix(size); + Boolean isBold = FALSE; /* setfont takes care of this */ + Boolean isItalic = FALSE; /* setfont takes care of this */ + ATSUAttributeValuePtr values[] = {&atsfont, &atsuSize, &isBold, &isItalic}; + + status = ATSUSetAttributes(style, 4, tags, sizes, values); + if (status!=noErr) + { + PyErr_SetString(PyExc_RuntimeError, "ATSUSetAttributes failed"); + return NULL; + } + + status = ATSUSetTextPointerLocation(layout, + text, + kATSUFromTextBeginning, /* offset from beginning */ + kATSUToTextEnd, /* length of text range */ + n); /* length of text buffer */ + if (status!=noErr) + { + PyErr_SetString(PyExc_RuntimeError, + "ATSUCreateTextLayoutWithTextPtr failed"); + return NULL; + } + + status = ATSUSetRunStyle(layout, + style, + kATSUFromTextBeginning, + kATSUToTextEnd); + if (status!=noErr) + { + PyErr_SetString(PyExc_RuntimeError, "ATSUSetRunStyle failed"); + return NULL; + } + + ATSUAttributeTag tag = kATSUCGContextTag; + ByteCount bc = sizeof (CGContextRef); + ATSUAttributeValuePtr value = &cr; + status = ATSUSetLayoutControls(layout, 1, &tag, &bc, &value); + if (status!=noErr) + { + PyErr_SetString(PyExc_RuntimeError, "ATSUSetLayoutControls failed"); + return NULL; + } + + ATSUTextMeasurement before; + ATSUTextMeasurement after; + ATSUTextMeasurement ascent; + ATSUTextMeasurement descent; + status = ATSUGetUnjustifiedBounds(layout, + kATSUFromTextBeginning, kATSUToTextEnd, + &before, &after, &ascent, &descent); + if (status!=noErr) + { + PyErr_SetString(PyExc_RuntimeError, "ATSUGetUnjustifiedBounds failed"); + return NULL; + } + + const float width = FixedToFloat(after-before); + const float height = FixedToFloat(ascent-descent); + + return Py_BuildValue("fff", width, height, FixedToFloat(descent)); +} +#endif + static void _data_provider_release(void* info, const void* data, size_t size) { PyObject* image = (PyObject*)info; @@ -2293,101 +2588,6 @@ } static PyObject* -GraphicsContext_get_text_width_height_descent(GraphicsContext* self, PyObject* args) -{ - const UniChar* text; - int n; - PyObject* family; - float size; - const char* weight; - const char* italic; - - ATSFontRef atsfont; - - CGContextRef cr = self->cr; - if (!cr) - { - PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL"); - return NULL; - } - - if(!PyArg_ParseTuple(args, "u#Ofss", &text, &n, &family, &size, &weight, &italic)) return NULL; - - atsfont = setfont(cr, family, size, weight, italic); - - OSStatus status = noErr; - ATSUAttributeTag tags[] = {kATSUFontTag, - kATSUSizeTag, - kATSUQDBoldfaceTag, - kATSUQDItalicTag}; - ByteCount sizes[] = {sizeof(ATSUFontID), - sizeof(Fixed), - sizeof(Boolean), - sizeof(Boolean)}; - Fixed atsuSize = Long2Fix(size); - Boolean isBold = FALSE; /* setfont takes care of this */ - Boolean isItalic = FALSE; /* setfont takes care of this */ - ATSUAttributeValuePtr values[] = {&atsfont, &atsuSize, &isBold, &isItalic}; - - status = ATSUSetAttributes(style, 4, tags, sizes, values); - if (status!=noErr) - { - PyErr_SetString(PyExc_RuntimeError, "ATSUSetAttributes failed"); - return NULL; - } - - status = ATSUSetTextPointerLocation(layout, - text, - kATSUFromTextBeginning, /* offset from beginning */ - kATSUToTextEnd, /* length of text range */ - n); /* length of text buffer */ - if (status!=noErr) - { - PyErr_SetString(PyExc_RuntimeError, - "ATSUCreateTextLayoutWithTextPtr failed"); - return NULL; - } - - status = ATSUSetRunStyle(layout, - style, - kATSUFromTextBeginning, - kATSUToTextEnd); - if (status!=noErr) - { - PyErr_SetString(PyExc_RuntimeError, "ATSUSetRunStyle failed"); - return NULL; - } - - ATSUAttributeTag tag = kATSUCGContextTag; - ByteCount bc = sizeof (CGContextRef); - ATSUAttributeValuePtr value = &cr; - status = ATSUSetLayoutControls(layout, 1, &tag, &bc, &value); - if (status!=noErr) - { - PyErr_SetString(PyExc_RuntimeError, "ATSUSetLayoutControls failed"); - return NULL; - } - - ATSUTextMeasurement before; - ATSUTextMeasurement after; - ATSUTextMeasurement ascent; - ATSUTextMeasurement descent; - status = ATSUGetUnjustifiedBounds(layout, - kATSUFromTextBeginning, kATSUToTextEnd, - &before, &after, &ascent, &descent); - if (status!=noErr) - { - PyErr_SetString(PyExc_RuntimeError, "ATSUGetUnjustifiedBounds failed"); - return NULL; - } - - const float width = FixedToFloat(after-before); - const float height = FixedToFloat(ascent-descent); - - return Py_BuildValue("fff", width, height, FixedToFloat(descent)); -} - -static PyObject* GraphicsContext_draw_image(GraphicsContext* self, PyObject* args) { float x, y; @@ -2621,7 +2821,11 @@ "_macosx.GraphicsContext", /*tp_name*/ sizeof(GraphicsContext), /*tp_basicsize*/ 0, /*tp_itemsize*/ +#ifdef MAC_OS_X_VERSION_10_5 + 0, /*tp_dealloc*/ +#else (destructor)GraphicsContext_dealloc, /*tp_dealloc*/ +#endif 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -2826,15 +3030,18 @@ int n; const unichar* characters; NSSize size; + double width, height; if(!view) { PyErr_SetString(PyExc_RuntimeError, "NSView* is NULL"); return NULL; } - if(!PyArg_ParseTuple(args, "u#ff", - &characters, &n, - &size.width, &size.height)) return NULL; + /* NSSize contains CGFloat; cannot use size directly */ + if(!PyArg_ParseTuple(args, "u#dd", + &characters, &n, &width, &height)) return NULL; + size.width = width; + size.height = height; /* This function may be called from inside the event loop, when an * autorelease pool is available, or from Python, when no autorelease @@ -4492,6 +4699,86 @@ PyGILState_Release(gstate); } +- (void)rightMouseDown:(NSEvent *)event +{ + int x, y; + int num = 3; + PyObject* result; + PyGILState_STATE gstate; + NSPoint location = [event locationInWindow]; + location = [self convertPoint: location fromView: nil]; + x = location.x; + y = location.y; + gstate = PyGILState_Ensure(); + result = PyObject_CallMethod(canvas, "button_press_event", "iii", x, y, num); + if(result) + Py_DECREF(result); + else + PyErr_Print(); + + PyGILState_Release(gstate); +} + +- (void)rightMouseUp:(NSEvent *)event +{ + int x, y; + int num = 3; + PyObject* result; + PyGILState_STATE gstate; + NSPoint location = [event locationInWindow]; + location = [self convertPoint: location fromView: nil]; + x = location.x; + y = location.y; + gstate = PyGILState_Ensure(); + result = PyObject_CallMethod(canvas, "button_release_event", "iii", x, y, num); + if(result) + Py_DECREF(result); + else + PyErr_Print(); + + PyGILState_Release(gstate); +} + +- (void)otherMouseDown:(NSEvent *)event +{ + int x, y; + int num = 2; + PyObject* result; + PyGILState_STATE gstate; + NSPoint location = [event locationInWindow]; + location = [self convertPoint: location fromView: nil]; + x = location.x; + y = location.y; + gstate = PyGILState_Ensure(); + result = PyObject_CallMethod(canvas, "button_press_event", "iii", x, y, num); + if(result) + Py_DECREF(result); + else + PyErr_Print(); + + PyGILState_Release(gstate); +} + +- (void)otherMouseUp:(NSEvent *)event +{ + int x, y; + int num = 2; + PyObject* result; + PyGILState_STATE gstate; + NSPoint location = [event locationInWindow]; + location = [self convertPoint: location fromView: nil]; + x = location.x; + y = location.y; + gstate = PyGILState_Ensure(); + result = PyObject_CallMethod(canvas, "button_release_event", "iii", x, y, num); + if(result) + Py_DECREF(result); + else + PyErr_Print(); + + PyGILState_Release(gstate); +} + - (void)setRubberband:(NSRect)rect { if (!NSIsEmptyRect(rubberband)) [self setNeedsDisplayInRect: rubberband]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |