10000 SC 2005/03/14 · matplotlib/matplotlib@8d28b4f · GitHub
[go: up one dir, main page]

Skip to content

Commit 8d28b4f

Browse files
author
Steve Chaplin
committed
SC 2005/03/14
svn path=/trunk/matplotlib/; revision=1075
1 parent dfc1c84 commit 8d28b4f

File tree

6 files changed

+180
-59
lines changed

6 files changed

+180
-59
lines changed

CHANGELOG

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
New entries should be added at the top
22

3+
2005-03-14 add src/_backend_gdk.c extension to provide a substitute function
4+
for pixbuf.get_pixels_array(). Currently pixbuf.get_pixels_array()
5+
only works with Numeric, and then only works if pygtk has been
6+
compiled with Numeric support. The change provides a function
7+
pixbuf_get_pixels_array() which works with Numeric and numarray and
8+
is always available. It means that backend_gtk should be able to
9+
display images and mathtext in all circumstances. - SC
10+
311
2005-03-11 Upgraded CXX to 5.3.1
412

513
2005-03-10 remove GraphicsContextPS.set_linestyle()

lib/matplotlib/backends/backend_cairo.py

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
import os, sys, warnings
2323
def _fn_name(): return sys._getframe(1).f_code.co_name
2424

25-
from matplotlib.numerix import asarray, pi, fromstring, UInt8, zeros
26-
import matplotlib.numerix as numerix
25+
import matplotlib.agg as agg
2726
from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\
2827
FigureManagerBase, FigureCanvasBase
2928
from matplotlib.cbook import enumerate, izip
3029
from matplotlib.figure import Figure
3130
from matplotlib.mathtext import math_parse_s_ft2font
31+
from matplotlib.numerix import asarray, pi, fromstring, UInt8, zeros
32+
import matplotlib.numerix as numerix
3233
from matplotlib.transforms import Bbox
3334

3435
import cairo
@@ -202,9 +203,7 @@ def draw_lines(self, gc, x, y, transform=None):
202203
ctx.set_matrix (matrix_old)
203204

204205

205-
#def draw_markers(self, gc, path, x, y, transform):
206-
def _draw_markers(self, gc, path, rgbFace, x, y, transform):
207-
# TODO 'path' has changed - needs updating
206+
def draw_markers(self, gc, path, rgbFace, x, y, transform):
208207
if DEBUG: print 'backend_cairo.RendererCairo.%s()' % _fn_name()
209208

210209
ctx = gc.ctx
@@ -223,35 +222,26 @@ def _draw_markers(self, gc, path, rgbFace, x, y, transform):
223222
#matrix = cairo.Matrix (*vec6)
224223
#ctx.set_matrix (matrix)
225224

225+
path_list = [path.vertex() for i in range(path.total_vertices())]
226+
226227
def generate_path (path):
227-
"""trace path and return fill_rgb
228-
coords are mpl points
229-
"""
230-
for p in path:
231-
code = p[0]
232-
if code == MOVETO:
233-
ctx.move_to (p[1], -p[2])
234-
elif code == LINETO:
235-
ctx.line_to (p[1], -p[2])
236-
elif code == ENDPOLY:
228+
for code, xp, yp in path_list:
229+
if code == agg.path_cmd_move_to:
230+
ctx.move_to (xp, -yp)
231+
elif code == agg.path_cmd_line_to:
232+
ctx.line_to (xp, -yp)
233+
elif code == agg.path_cmd_end_poly:
237234
ctx.close_path()
238-
#if p[1]: # fill
239-
# #rgba = p[2:]
240-
# return p[2:5] # don't really want to read the same fill_rgb every time we generate_path()
241-
#return None
242235

243236
for x,y in izip(x,y):
244237
ctx.save()
245238
ctx.new_path()
246239
ctx.translate(x, self.height - y)
247-
248-
#fill_rgb = generate_path (path)
249240
generate_path (path)
250-
#if fill_rgb:
241+
251242
if rgbFace:
252243
ctx.save()
253-
#ctx.set_rgb_color (*fill_rgb)
254-
ctx.set_rgb_color (rgbFace)
244+
ctx.set_rgb_color (*rgbFace)
255245
# later - set alpha also?
256246
ctx.fill()
257247
ctx.restore() # undo colour change and restore path

lib/matplotlib/backends/backend_gdk.py

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ def fn_name(): return sys._getframe(1).f_code.co_name
3737
backend_version = "%d.%d.%d" % gtk.pygtk_version
3838
del pygtk_version_required
3939

40+
# do after gtk else get "pygtk.require() must be called before importing gtk" errors
41+
if numerix.which[0] == "numarray":
42+
from matplotlib._na_backend_gdk import pixbuf_get_pixels_array
43+
else:
44+
from matplotlib._nc_backend_gdk import pixbuf_get_pixels_array
45+
4046

4147
DEBUG = False
4248

@@ -107,23 +113,17 @@ def draw_image(self, x, y, im, origin, bbox):
107113
# set clip rect?
108114

109115
flipud = origin=='lower'
110-
rows, cols, s = im.as_str(flipud)
116+
rows, cols, image_str = im.as_str(flipud)
111117

112-
X = fromstring(s, UInt8)
113-
X.shape = rows, cols, 4
118+
image_array = fromstring(image_str, UInt8)
119+
image_array.shape = rows, cols, 4
114120

115-
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,
116-
has_alpha=True, bits_per_sample=8,
117-
width=cols, height=rows)
118-
try:
119-
pa = pb.get_pixels_array() # new in 2.2
120-
except AttributeError:
121-
pa = pb.pixel_array # deprecated in 2.2
122-
except RuntimeError, exc: # pygtk was not compiled with Numeric Python support
123-
warnings.warn('draw_image not supported: %s' % exc)
124-
return
121+
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,
122+
has_alpha=True, bits_per_sample=8,
123+
width=cols, height=rows)
125124

126-
pa[:,:,:] = X
125+
array = pixbuf_get_pixels_array(pixbuf)
126+
array[:,:,:] = image_array
127127

128128
gc = self.new_gc()
129129

@@ -132,12 +132,12 @@ def draw_image(self, x, y, im, origin, bbox):
132132

133133
try: # new in 2.2
134134
# can use None instead of gc.gdkGC, if don't need clipping
135-
self.gdkDrawable.draw_pixbuf (gc.gdkGC, pb, 0, 0,
135+
self.gdkDrawable.draw_pixbuf (gc.gdkGC, pixbuf, 0, 0,
136136
int(x), int(y), cols, rows,
137137
gdk.RGB_DITHER_NONE, 0, 0)
138138
except AttributeError:
139139
# deprecated in 2.2
140-
pb.render_to_drawable(self.gdkDrawable, gc.gdkGC, 0, 0,
140+
pixbuf.render_to_drawable(self.gdkDrawable, gc.gdkGC, 0, 0,
141141
int(x), int(y), cols, rows,
142142
gdk.RGB_DITHER_NONE, 0, 0)
143143

@@ -211,7 +211,7 @@ def _draw_mathtext(self, gc, x, y, s, prop, angle):
211211
x -= width
212212
y -= height
213213

214-
imw, imh, s = fonts[0].image_as_str()
214+
imw, imh, image_str = fonts[0].image_as_str()
215215
N = imw*imh
216216

217217
# a numpixels by num fonts array
@@ -220,40 +220,34 @@ def _draw_mathtext(self, gc, x, y, s, prop, angle):
220220
for i, font in enumerate(fonts):
221221
if angle == 90:
222222
font.horiz_image_to_vert_image() # <-- Rotate
223-
imw, imh, s = font.image_as_str()
224-
Xall[:,i] = fromstring(s, UInt8)
223+
imw, imh, image_str = font.image_as_str()
224+
Xall[:,i] = fromstring(image_str, UInt8)
225225

226226
# get the max alpha at each pixel
227227
Xs = numerix.mlab.max(Xall,1)
228228

229229
# convert it to it's proper shape
230230
Xs.shape = imh, imw
231231

232-
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=True,
233-
bits_per_sample=8, width=imw, height=imh)
232+
pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=True,
233+
bits_per_sample=8, width=imw, height=imh)
234234

235-
try:
236-
pa = pb.get_pixels_array() # new in 2.2
237-
except AttributeError:
238-
pa = pb.pixel_array # deprecated in 2.2
239-
except RuntimeError, exc: # 'pygtk was not compiled with Numeric Python support'
240-
warnings.warn('mathtext not supported: %s' % exc)
241-
return
235+
array = pixbuf_get_pixels_array(pixbuf)
242236

243237
rgb = gc.get_rgb 10000 ()
244-
pa[:,:,0]=int(rgb[0]*255)
245-
pa[:,:,1]=int(rgb[1]*255)
246-
pa[:,:,2]=int(rgb[2]*255)
247-
pa[:,:,3]=Xs
238+
array[:,:,0]=int(rgb[0]*255)
239+
array[:,:,1]=int(rgb[1]*255)
240+
array[:,:,2]=int(rgb[2]*255)
241+
array[:,:,3]=Xs
248242

249243
try: # new in 2.2
250244
# can use None instead of gc.gdkGC, if don't need clipping
251-
self.gdkDrawable.draw_pixbuf (gc.gdkGC, pb, 0, 0,
245+
self.gdkDrawable.draw_pixbuf (gc.gdkGC, pixbuf, 0, 0,
252246
int(x), int(y), imw, imh,
253247
gdk.RGB_DITHER_NONE, 0, 0)
254248
except AttributeError:
255249
# deprecated in 2.2
256-
pb.render_to_drawable(self.gdkDrawable, gc.gdkGC, 0, 0,
250+
pixbuf.render_to_drawable(self.gdkDrawable, gc.gdkGC, 0, 0,
257251
int(x), int(y), imw, imh,
258252
gdk.RGB_DITHER_NONE, 0, 0)
259253

setup.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#BUILD_GTKAGG = 0
3131
BUILD_GTKAGG = 'auto'
3232

33+
BUILD_GTK = 'auto'
34+
3335
# build TK GUI with Agg renderer ; requires Tkinter Python extension
3436
# and Tk includes
3537
# Use False or 0 if you don't want to build
@@ -54,7 +56,7 @@
5456
from distutils.core import Extension
5557
from setupext import build_agg, build_gtkagg, build_tkagg, \
5658
build_ft2font, build_image, build_windowing, build_transforms, \
57-
build_contour, build_enthought, build_swigagg
59+
build_contour, build_enthought, build_swigagg, build_gdk
5860
import distutils.sysconfig
5961

6062
major, minor1, minor2, s, tmp = sys.version_info
@@ -153,6 +155,16 @@ def add_dateutil():
153155
build_transforms(ext_modules, packages, NUMERIX)
154156
build_enthought(ext_modules, packages)
155157

158+
if BUILD_GTK:
159+
try:
160+
import gtk
161+
except ImportError:
162+
print 'GTK requires pygtk'
163+
BUILD_GTK=0
164+
except RuntimeError:
165+
print 'pygtk present but import failed'
166+
build_gdk(ext_modules, packages, NUMERIX)
167+
156168
if BUILD_GTKAGG:
157169
try:
158170
import gtk

setupext.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@
6060
BUILT_WINDOWING = False
6161
BUILT_CONTOUR = False
6262
BUILT_ENTHOUGHT = False
63+
BUILT_CONTOUR = False
64+
BUILT_GDK = False
65+
6366

6467
class CleanUpFile:
6568
"""CleanUpFile deletes the specified filename when self is destroyed."""
@@ -567,5 +570,34 @@ def build_contour(ext_modules, packages, numerix):
567570
BUILT_CONTOUR = True
568571

569572

573+
def build_gdk(ext_modules, packages, numerix):
574+
global BUILT_GDK
575+
if BUILT_GDK: return # only build it if you you haven't already
570576

577+
if numerix in ["numarray","both"]: # Build for numarray
578+
temp_copy('src/_backend_gdk.c', 'src/_na_backend_gdk.c')
579+
module = Extension(
580+
'matplotlib._na_backend_gdk',
581+
[ 'src/_na_backend_gdk.c',
582+
],
583+
libraries = [],
584+
)
585+
module.extra_compile_args.append('-DNUMARRAY=1')
586+
add_base_flags(module)
587+
add_pygtk_flags(module)
588+
ext_modules.append(module)
589+
590+
if numerix in ["Numeric","both"]: # Build for Numeric
591+
temp_copy('src/_backend_gdk.c', 'src/_nc_backend_gdk.c')
592+
module = Extension(
593+
'matplotlib._nc_backend_gdk',
594+
[ 'src/_nc_backend_gdk.c',
595+
],
596+
libraries = [],
597+
)
598+
module.extra_compile_args.append('-DNUMERIC=1')
599+
add_base_flags(module)
600+
add_pygtk_flags(module)
601+
ext_modules.append(module)
571602

603+
BUILT_GDK = True

src/_backend_gdk.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* -*- mode: C; c-basic-offset: 4 -*-
2+
* C extensions for backend_gdk
3+
*/
4+
5+
#include "Python.h"
6+
#ifdef NUMARRAY
7+
#include "numarray/arrayobject.h"
8+
#else
9+
#include "Numeric/arrayobject.h"
10+
#endif
11+
12+
#include <pygtk/pygtk.h>
13+
#include <gdk/gdkx.h>
14+
15+
16+
static PyTypeObject *_PyGdkPixbuf_Type;
17+
#define PyGdkPixbuf_Type (*_PyGdkPixbuf_Type)
18+
19+
/* Implement an equivalent to the pygtk method pixbuf.get_pixels_array()
20+
* Fedora 1,2,3 (for example) has PyGTK but does not have Numeric
21+
* and so does not have pixbuf.get_pixels_array().
22+
* Also provide numarray as well as Numeric support
23+
*/
24+
25+
static PyObject *
26+
pixbuf_get_pixels_array(PyObject *self, PyObject *args)
27+
{
28+
/* 1) read in Python pixbuf, get the underlying C pixbuf */
29+
PyGObject *py_pixbuf;
30+
GdkPixbuf *pixbuf;
31+
PyArrayObject *array;
32+
int dims[3] = { 0, 0, 3 };
33+
34+
if (!PyArg_ParseTuple(args, "O!:pixbuf_get_pixels_array",
35+
&PyGdkPixbuf_Type, &py_pixbuf))
36+
return NULL;
37+
38+
pixbuf = GDK_PIXBUF(py_pixbuf->obj);
39+
40+
/* 2) same as pygtk/gtk/gdk.c _wrap_gdk_pixbuf_get_pixels_array()
41+
* with 'self' changed to py_pixbuf
42+
*/
43+
44+
dims[0] = gdk_pixbuf_get_height(pixbuf);
45+
dims[1] = gdk_pixbuf_get_width(pixbuf);
46+
if (gdk_pixbuf_get_has_alpha(pixbuf))
47+
dims[2] = 4;
48+
49+
array = (PyArrayObject *)PyArray_FromDimsAndData(3, dims, PyArray_UBYTE,
50+
(char *)gdk_pixbuf_get_pixels(pixbuf));
51+
52+
if (array == NULL)
53+
return NULL;
54+
55+
array->strides[0] = gdk_pixbuf_get_rowstride(pixbuf);
56+
/* the array holds a ref to the pixbuf pixels through this wrapper*/
57+
Py_INCREF(py_pixbuf);
58+
array->base = (PyObject *)py_pixbuf;
59+
return PyArray_Return(array);
60+
}
61+
62+
static PyMethodDef _backend_gdk_functions[] = {
63+
{ "pixbuf_get_pixels_array", (PyCFunction)pixbuf_get_pixels_array, METH_VARARGS< AF10 /span> },
64+
{ NULL, NULL, 0 }
65+
};
66+
67+
DL_EXPORT(void)
68+
#ifdef NUMARRAY
69+
init_na_backend_gdk(void)
70+
{
71+
PyObject *mod;
72+
mod = Py_InitModule("_na_backend_gdk", _backend_gdk_functions);
73+
#else
74+
init_nc_backend_gdk(void)
75+
{
76+
PyObject *mod;
77+
mod = Py_InitModule("_nc_backend_gdk", _backend_gdk_functions);
78+
#endif
79+
80+
import_array();
81+
init_pygtk();
82+
83+
mod = PyImport_ImportModule("gtk.gdk");
84+
_PyGdkPixbuf_Type = (PyTypeObject *)PyObject_GetAttrString(mod, "Pixbuf");
85+
}

0 commit comments

Comments
 (0)
0