summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorAndrew M. Kuchling <amk@amk.ca>2000-06-18 18:45:50 (GMT)
committerAndrew M. Kuchling <amk@amk.ca>2000-06-18 18:45:50 (GMT)
commite475e70128e5e12392faa10f6556460c308efc0a (patch)
treed6b30e75b24f410540f9087b571d338f3b885064 /Modules
parent74042d6e5d44cc9d332c28414a1e04eadd204248 (diff)
downloadcpython-e475e70128e5e12392faa10f6556460c308efc0a.zip
cpython-e475e70128e5e12392faa10f6556460c308efc0a.tar.gz
cpython-e475e70128e5e12392faa10f6556460c308efc0a.tar.bz2
Patch from /F:
this patch adds a fast _flatten function to the _tkinter module, and imports it from Tkinter.py (if available). this speeds up canvas operations like create_line and create_polygon. for example, a create_line with 5000 vertices runs about 50 times faster with this patch in place.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_tkinter.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 6c3beef..baf117d 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -1978,6 +1978,105 @@ static PyTypeObject Tkapp_Type =
/**** Tkinter Module ****/
+typedef struct {
+ PyObject* tuple;
+ int size; /* current size */
+ int maxsize; /* allocated size */
+} FlattenContext;
+
+static int
+_bump(FlattenContext* context, int size)
+{
+ /* expand tuple to hold (at least) size new items. return true if
+ successful, false if an exception was raised*/
+
+ int maxsize = context->maxsize * 2;
+
+ if (maxsize < context->size + size)
+ maxsize = context->size + size;
+
+ context->maxsize = maxsize;
+
+ return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
+}
+
+static int
+_flatten1(FlattenContext* context, PyObject* item)
+{
+ /* add tuple or list to argument tuple (recursively) */
+
+ int i, size;
+
+ if (PyList_Check(item)) {
+ size = PyList_GET_SIZE(item);
+ /* preallocate (assume no nesting) */
+ if (context->size + size > context->maxsize && !_bump(context, size))
+ return 0;
+ /* copy items to output tuple */
+ for (i = 0; i < size; i++) {
+ PyObject *o = PyList_GET_ITEM(item, i);
+ if (PyList_Check(o) || PyTuple_Check(o)) {
+ if (!_flatten1(context, o))
+ return 0;
+ } else if (o != Py_None) {
+ if (context->size + 1 > context->maxsize && !_bump(context, 1))
+ return 0;
+ Py_INCREF(o);
+ PyTuple_SET_ITEM(context->tuple, context->size++, o);
+ }
+ }
+ } else if (PyTuple_Check(item)) {
+ /* same, for tuples */
+ size = PyTuple_GET_SIZE(item);
+ if (context->size + size > context->maxsize && !_bump(context, size))
+ return 0;
+ for (i = 0; i < size; i++) {
+ PyObject *o = PyTuple_GET_ITEM(item, i);
+ if (PyList_Check(o) || PyTuple_Check(o)) {
+ if (!_flatten1(context, o))
+ return 0;
+ } else if (o != Py_None) {
+ if (context->size + 1 > context->maxsize && !_bump(context, 1))
+ return 0;
+ Py_INCREF(o);
+ PyTuple_SET_ITEM(context->tuple, context->size++, o);
+ }
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError, "argument must be sequence");
+ return 0;
+ }
+ return 1;
+}
+
+static PyObject *
+Tkinter_Flatten(PyObject* self, PyObject* args)
+{
+ FlattenContext context;
+ PyObject* item;
+
+ if (!PyArg_ParseTuple(args, "O:_flatten", &item))
+ return NULL;
+
+ context.maxsize = PySequence_Length(item);
+ if (context.maxsize <= 0)
+ return PyTuple_New(0);
+
+ context.tuple = PyTuple_New(context.maxsize);
+ if (!context.tuple)
+ return NULL;
+
+ context.size = 0;
+
+ if (!_flatten1(&context, item))
+ return NULL;
+
+ if (_PyTuple_Resize(&context.tuple, context.size, 0))
+ return NULL;
+
+ return context.tuple;
+}
+
static PyObject *
Tkinter_Create(self, args)
PyObject *self;
@@ -2006,6 +2105,7 @@ Tkinter_Create(self, args)
static PyMethodDef moduleMethods[] =
{
+ {"_flatten", Tkinter_Flatten, 1},
{"create", Tkinter_Create, 1},
#ifdef HAVE_CREATEFILEHANDLER
{"createfilehandler", Tkapp_CreateFileHandler, 1},