Staging
v0.8.1
v0.8.1
https://github.com/python/cpython
Tip revision: 74f4bd53e03ded8408bcc2de67cf0f5a4ac5b1a1 authored by Barry Warsaw on 23 February 2012, 15:59:38 UTC
Bump some more copyright years (as per PEP 101), since this is the first
Bump some more copyright years (as per PEP 101), since this is the first
Tip revision: 74f4bd5
drawfmodule.c
/* drawf DrawFile functions */
#include "oslib/os.h"
#include "oslib/osfile.h"
#include "oslib/drawfile.h"
#include "Python.h"
#include <limits.h>
#define PyDrawF_Check(op) ((op)->ob_type == &PyDrawFType)
#define HDRSIZE 40
#define GRPHDRSIZE 36
#define DRAWTYPE 0xaff
#define NEXT(d) ((drawfile_object*)((char*)(d)+(d)->size))
typedef struct
{ PyObject_HEAD
drawfile_diagram *drawf;
int size; /*length in bytes*/
int nobjs; /* no of objects */
} PyDrawFObject;
typedef struct dheader
{ char tag [4];
int major_version;
int minor_version;
char source [12];
os_box bbox;
} dheader;
static PyObject *DrawFError; /* Exception drawf.error */
static os_error *e;
static PyTypeObject PyDrawFType;
static dheader header=
{ {'D','r','a','w'},
201,0,
{'P','y','t','h','o','n',' ',' ',' ',' ',' ',' '},
{INT_MAX,INT_MAX,INT_MIN,INT_MIN}
};
static PyObject *drawf_oserror(void)
{ PyErr_SetString(DrawFError,e->errmess);
return 0;
}
static PyObject *drawf_error(char *s)
{ PyErr_SetString(DrawFError,s);
return 0;
}
/* DrawFile commands */
static void countobjs(PyDrawFObject *pd)
{ int k=0,q;
drawfile_diagram *dd=pd->drawf;
drawfile_object *d=dd->objects;
char *end=(char*)dd+pd->size;
pd->nobjs=-1;
while((char*)d<end)
{ k++;
q=d->size;
if(q<=0||q&3) return ;
d=NEXT(d);
}
if ((char*)d==end) pd->nobjs=k;
}
static drawfile_object *findobj(PyDrawFObject *pd,Py_ssize_t n)
{ drawfile_diagram *dd=pd->drawf;
drawfile_object *d=dd->objects;
for(;n>0;n--) d=NEXT(d);
return d;
}
static PyDrawFObject* new(int size)
{ PyDrawFObject *b=PyObject_NEW(PyDrawFObject,&PyDrawFType);
if(!b) return NULL;
size+=HDRSIZE;
b->drawf=malloc(size);
if(!b->drawf)
{ Py_DECREF(b);
return (PyDrawFObject*)PyErr_NoMemory();
}
b->size=size;
return b;
}
static void extend(os_box *b,os_box *c)
{ if(b->x0>c->x0) b->x0=c->x0;
if(b->y0>c->y0) b->y0=c->y0;
if(b->x1<c->x1) b->x1=c->x1;
if(b->y1<c->y1) b->y1=c->y1;
}
static PyObject *DrawF_New(PyObject *self,PyObject *args)
{ PyDrawFObject *b;
if(!PyArg_ParseTuple(args,"")) return NULL;
b=new(0);
if(!b) return NULL;
*((dheader*)b->drawf)=header;
b->nobjs=0;
return (PyObject *)b;
}
static PyObject *DrawF_Load(PyObject *self,PyObject *args)
{ int size;
char *fname;
PyDrawFObject *b;
fileswitch_object_type ot;
if(!PyArg_ParseTuple(args,"s",&fname)) return NULL;
e=xosfile_read_no_path(fname,&ot,0,0,&size,0);
if(e) return drawf_oserror();
size-=HDRSIZE;
if(ot!=osfile_IS_FILE||size<0||size&3) return drawf_error("Bad draw file");
b=new(size);
if(!b) return NULL;
e=xosfile_load_stamped_no_path(fname,(byte*)(b->drawf),0,0,0,0,0);
if(e)
{ Py_DECREF(b);
return drawf_oserror();
}
countobjs(b);
if(b->nobjs>=0) return (PyObject *)b;
Py_DECREF(b);
return drawf_error("Corrupt draw file");
}
static PyObject *DrawF_Save(PyDrawFObject *self,PyObject *arg)
{ char *fname;
if(!PyArg_ParseTuple(arg,"s",&fname)) return NULL;
e=xosfile_save_stamped(fname,DRAWTYPE,
(byte*)(self->drawf),(byte*)(self->drawf)+self->size);
if (e) return drawf_oserror();
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_Render(PyDrawFObject *self,PyObject *arg)
{ int flags,trans,clip,flat;
if(!PyArg_ParseTuple(arg,"iiii",&flags,&trans,&clip,&flat)) return NULL;
e=xdrawfile_render((drawfile_render_flags)flags,self->drawf,self->size,
(os_trfm*)trans,(os_box*)clip,flat);
if(e) return drawf_oserror();
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_Path(PyDrawFObject *self,PyObject *arg)
{ PyObject *pl;
PyObject *dp=0;
os_colour fill;
os_colour outline;
int width,start=0;
drawfile_path_style style;
int size=40;
int n,i,element_count;
drawfile_diagram *diag;
drawfile_object *dobj;
drawfile_path *dpath;
draw_path *thepath;
draw_line_style line_style;
draw_dash_pattern *dash_pattern=0;
os_box *box;
long *pe;
if(!PyArg_ParseTuple(arg,"O!(iiii)|O!i",&PyList_Type,&pl,(int*)&fill,
(int*)&outline,&width,(int*)&style,&PyTuple_Type,&dp,&start)) return NULL;
if(dp)
{ element_count=PyTuple_Size(dp);
size+=4*element_count+8;
style.flags|=drawfile_PATH_DASHED;
}
else style.flags&=~drawfile_PATH_DASHED;
n=PyList_Size(pl);
size+=4*n+8;
for(i=0;i<n;i++) if(!PyInt_Check(PyList_GetItem(pl,i))) size+=4;
diag=realloc(self->drawf,self->size+size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
dobj=(drawfile_object*)((char*)diag+self->size);
dobj->type=drawfile_TYPE_PATH;
dobj->size=size;
dpath=&dobj->data.path;
self->size+=size;
self->nobjs++;
box=&dpath->bbox;
dpath->fill=fill;dpath->outline=outline;
dpath->width=width;dpath->style=style;
pe=(long*)&(dpath->path);
if(dp)
{ dash_pattern=&(((drawfile_path_with_pattern*)dpath)->pattern);
dash_pattern->start=start;
dash_pattern->element_count=element_count;
for(i=0;i<element_count;i++)
{ dash_pattern->elements[i]=(int)PyInt_AsLong(PyTuple_GetItem(dp,i));
}
pe+=element_count+2;
}
thepath=(draw_path*)pe;
*pe++=draw_MOVE_TO;
for(i=0;i<n;i++)
{ PyObject *p=PyList_GetItem(pl,i);
if(PyInt_Check(p))
*pe++=PyInt_AsLong(p);
else
{
*pe++=PyInt_AsLong(PyTuple_GetItem(p,0));
*pe++=PyInt_AsLong(PyTuple_GetItem(p,1));
}
}
*pe=draw_END_PATH;
line_style.join_style=style.flags&3;
line_style.end_cap_style=(style.flags&3)>>2;
line_style.start_cap_style=(style.flags&3)>>4;
line_style.reserved=0;
line_style.mitre_limit=10;
line_style.start_cap_width=style.cap_width;
line_style.end_cap_width=style.cap_width;
line_style.start_cap_length=style.cap_length;
line_style.end_cap_length=style.cap_length;
e=xdraw_process_path(thepath,0x70000000,0,0,width,&line_style,dash_pattern,
(draw_output_path)((char*)box+0x80000000),0);
if(e) return drawf_oserror();
/* draw_process_path seems to have a bug:
If the bounding box size is zero, it returns 0x7FFFFFFF, ..., 0x80000000 instead of the
correct size. */
if (box->x0==0x7FFFFFFF)
{
/* path has zero extension, so forget it; it would be invisible anyway */
self->size-=size;
self->nobjs--;
diag=realloc(self->drawf,self->size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
}
else
extend(&(diag->bbox),box);
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_Text(PyDrawFObject *self,PyObject *arg)
{ os_colour fill,bg_hint;
drawfile_text_style style;
int xsize,ysize,x,y;
int size,len;
char *text;
drawfile_diagram *diag;
drawfile_object *dobj;
drawfile_text *dtext;
os_box *box;
if(!PyArg_ParseTuple(arg,"(ii)s(iiiii)",&x,&y,&text,
(int*)&fill,(int*)&bg_hint,(int*)&style,&xsize,&ysize)) return NULL;
len=strlen(text);
size=((len+4)&(~3))+52;
diag=realloc(self->drawf,self->size+size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
dobj=(drawfile_object*)((char*)diag+self->size);
dobj->type=drawfile_TYPE_TEXT;
dobj->size=size;
dtext=&dobj->data.text;
self->size+=size;
self->nobjs++;
dtext->fill=fill;
dtext->bg_hint=bg_hint;
dtext->style=style;
dtext->xsize=xsize;
dtext->ysize=ysize;
dtext->base.x=x;
dtext->base.y=y;
memset(dtext->text,0,(len+4)&(~3));
sprintf(dtext->text,"%s",text);
box=&(dtext->bbox);
box->x0=x;box->y0=y;box->x1=x+len*xsize;box->y1=y+ysize;
extend(&(diag->bbox),box);
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_TText(PyDrawFObject *self,PyObject *arg)
{ os_colour fill,bg_hint;
drawfile_text_style style;
int xsize,ysize,x,y;
int t1,t2,t3,t4,t5,t6;
int size,len;
char *text;
drawfile_diagram *diag;
drawfile_object *dobj;
drawfile_trfm_text *dtext;
os_box *box;
t1=1<<16;t2=0;
t3=0;t4=1<<16;
t5=t6=0;
if(!PyArg_ParseTuple(arg,"(ii)s(iiiii)|(iiiiii)",&x,&y,&text,
(int*)&fill,(int*)&bg_hint,(int*)&style,&xsize,&ysize,&t1,&t2,&t3,&t4,&t5,&t6)) return NULL;
len=strlen(text);
size=((len+4)&(~3))+52+28;
diag=realloc(self->drawf,self->size+size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
dobj=(drawfile_object*)((char*)diag+self->size);
dobj->type=drawfile_TYPE_TRFM_TEXT;
dobj->size=size;
dtext=&dobj->data.trfm_text;
self->size+=size;
self->nobjs++;
dtext->trfm.entries[0][0]=t1;
dtext->trfm.entries[0][1]=t2;
dtext->trfm.entries[1][0]=t3;
dtext->trfm.entries[1][1]=t4;
dtext->trfm.entries[2][0]=t5;
dtext->trfm.entries[2][1]=t6;
dtext->flags=0;
dtext->fill=fill;
dtext->bg_hint=bg_hint;
dtext->style=style;
dtext->xsize=xsize;
dtext->ysize=ysize;
dtext->base.x=x;
dtext->base.y=y;
memset(dtext->text,0,(len+4)&(~3));
sprintf(dtext->text,"%s",text);
box=&(dtext->bbox);
box->x0=x;box->y0=y;box->x1=x+len*xsize;box->y1=y+ysize;
extend(&(diag->bbox),box);
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_FontTable(PyDrawFObject *self,PyObject *arg)
{ int size=8,n=0;
PyObject *d,*key,*value;
drawfile_diagram *diag;
drawfile_object *dobj;
char *dtable;
if(!PyArg_ParseTuple(arg,"O!",&PyDict_Type,&d)) return NULL;
while(PyDict_Next(d,&n,&key,&value))
{ int m=PyString_Size(value);
if(m<0||!PyInt_Check(key)) return NULL;
size+=m+2;
}
size=(size+3)&(~3);
diag=realloc(self->drawf,self->size+size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
dobj=(drawfile_object*)((char*)diag+self->size);
dobj->type=drawfile_TYPE_FONT_TABLE;
dobj->size=size;
dtable=(char*)(&dobj->data.font_table);
self->size+=size;
self->nobjs++;
memset(dtable,0,size-8);
n=0;
while(PyDict_Next(d,&n,&key,&value))
{ int m=PyString_Size(value);
*dtable=(char)PyInt_AsLong(key);
strcpy(dtable+1,PyString_AsString(value));
dtable+=m+2;
}
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_Group(PyDrawFObject *self,PyObject *arg)
{ int size,n;
PyDrawFObject *g;
char *name="";
drawfile_diagram *diag;
drawfile_object *dobj;
drawfile_group *dgroup;
if(!PyArg_ParseTuple(arg,"O!|s",&PyDrawFType,(PyObject*)&g,&name))
return NULL;
size=g->size-4;
diag=realloc(self->drawf,self->size+size);
if(!diag) return PyErr_NoMemory();
self->drawf=diag;
self->nobjs++;
dobj=(drawfile_object*)((char*)diag+self->size);
self->size+=size;
dobj->type=drawfile_TYPE_GROUP;
dobj->size=g->size-4;
dgroup=&dobj->data.group;
dgroup->bbox=g->drawf->bbox;
memset(dgroup->name,' ',12);
n=strlen(name);
if(n>12) n=12;
memcpy(dgroup->name,name,n);
memcpy((char*)dgroup->objects,(char*)g->drawf+40,g->size-40);
extend(&(diag->bbox),&(dgroup->bbox));
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_Find(PyDrawFObject *self,PyObject *arg)
{ int x,y,n=0;
int r=-1;
drawfile_object *d;
if(!PyArg_ParseTuple(arg,"ii|i",&x,&y,&n)) return NULL;
if(n<self->nobjs&&n>=0)
{ d=findobj(self,n);
while(n<self->nobjs)
{ if(x>=d->data.text.bbox.x0&&x<=d->data.text.bbox.x1&&
y>=d->data.text.bbox.y0&&y<=d->data.text.bbox.y1) { r=n;break;}
n++;
d=NEXT(d);
}
}
return PyInt_FromLong(r);
}
static PyObject *DrawF_Box(PyDrawFObject *self,PyObject *arg)
{ int n=-1;
os_box *box;
if(!PyArg_ParseTuple(arg,"|i",&n)) return NULL;
if(n>=self->nobjs|n<0) box=&(self->drawf->bbox);
else box=&(findobj(self,n)->data.text.bbox);
return Py_BuildValue("iiii",box->x0,box->y0,box->x1,box->y1);
}
static void SetBlock(drawfile_object *d,int size,int type,int offset,int value)
{ char *end=(char*)d+size;
printf("s%d t%d o%d v%d\n",size,type,offset,value);
for(;(char*)d<end;d=NEXT(d))
if(d->type==type) ((int*)(d))[offset]=value;
else if(d->type==drawfile_TYPE_GROUP)
SetBlock((drawfile_object*)&d->data.group.objects,
d->size,type,offset,value);
printf("SetBlock Done\n");
}
static PyObject *SetWord(PyDrawFObject *self,PyObject *arg,int type,int offset)
{ int n=PyTuple_Size(arg);
int m,value,q;
PyObject *par;
drawfile_object *e,*d=self->drawf->objects;
if(n==0) return drawf_error("Value Required");
par=PyTuple_GetItem(arg,0);
if(!PyInt_Check(par))
{ PyErr_SetString(PyExc_TypeError,"Int Required");
return 0;
}
value=(int)PyInt_AsLong(par);
if(n==1) SetBlock(d,self->size-HDRSIZE,type,offset,value);
else
{ for(m=1;m<n;m++)
{ par=PyTuple_GetItem(arg,m);
if(!PyInt_Check(par))
{ PyErr_SetString(PyExc_TypeError,"Int Required");
return 0;
}
q=(int)PyInt_AsLong(par);
if(q<0||q>=self->nobjs)
{ PyErr_SetString(PyExc_ValueError,"Object out of range");
return 0;
}
e=d;
for(;q>0;q--) e=NEXT(e);
if(e->type==type)
{ ((int*)(e))[offset]=value;
}
else if(e->type==drawfile_TYPE_GROUP)
SetBlock((drawfile_object*)&e->data.group.objects,
e->size-GRPHDRSIZE,type,offset,value);
}
}
Py_INCREF(Py_None);return Py_None;
}
static PyObject *DrawF_PathFill(PyDrawFObject *self,PyObject *arg)
{ return SetWord(self,arg,drawfile_TYPE_PATH,6);
}
static PyObject *DrawF_PathColour(PyDrawFObject *self,PyObject *arg)
{ return SetWord(self,arg,drawfile_TYPE_PATH,7);
}
static PyObject *DrawF_TextColour(PyDrawFObject *self,PyObject *arg)
{ return SetWord(self,arg,drawfile_TYPE_TEXT,6);
}
static PyObject *DrawF_TextBackground(PyDrawFObject *self,PyObject *arg)
{ return SetWord(self,arg,drawfile_TYPE_TEXT,7);
}
static struct PyMethodDef PyDrawF_Methods[]=
{
{ "render",(PyCFunction)DrawF_Render,1},
{ "save",(PyCFunction)DrawF_Save,1},
{ "path",(PyCFunction)DrawF_Path,1},
{ "text",(PyCFunction)DrawF_Text,1},
{ "ttext",(PyCFunction)DrawF_TText,1},
{ "fonttable",(PyCFunction)DrawF_FontTable,1},
{ "group",(PyCFunction)DrawF_Group,1},
{ "find",(PyCFunction)DrawF_Find,1},
{ "box",(PyCFunction)DrawF_Box,1},
{ "pathfill",(PyCFunction)DrawF_PathFill,1},
{ "pathcolour",(PyCFunction)DrawF_PathColour,1},
{ "textcolour",(PyCFunction)DrawF_TextColour,1},
{ "textbackground",(PyCFunction)DrawF_TextBackground,1},
{ NULL,NULL} /* sentinel */
};
static int drawf_len(PyDrawFObject *b)
{ return b->nobjs;
}
static PyObject *drawf_concat(PyDrawFObject *b,PyDrawFObject *c)
{ int size=b->size+c->size-2*HDRSIZE;
PyDrawFObject *p=new(size);
drawfile_diagram *dd;
drawfile_object *d;
int n;
if(!p) return NULL;
dd=p->drawf;
d=(drawfile_object*)((char*)dd+b->size);
memcpy((char*)dd,(char*)(b->drawf),b->size);
memcpy(d,(char*)(c->drawf)+HDRSIZE,c->size-HDRSIZE);
p->nobjs=b->nobjs+c->nobjs;
for(n=c->nobjs;n>0;n--)
{ extend(&(dd->bbox),&(d->data.path.bbox));
d=NEXT(d);
}
return (PyObject*)p;
}
static PyObject *drawf_repeat(PyDrawFObject *b,Py_ssize_t i)
{ PyErr_SetString(PyExc_IndexError,"drawf repetition not implemented");
return NULL;
}
static PyObject *drawf_item(PyDrawFObject *b,Py_ssize_t i)
{ PyDrawFObject *c;
Py_ssize_t size;
drawfile_diagram *dd;
drawfile_object *d;
if(i<0||i>=b->nobjs)
{ PyErr_SetString(PyExc_IndexError,"drawf index out of range");
return NULL;
}
d=findobj(b,i);
size=(char*)findobj(b,i+1)-(char*)d;
c=new(size);
if(!c) return NULL;
dd=c->drawf;
*((dheader*)dd)=header;
memcpy(dd->objects,d,size);
c->nobjs=1;
extend(&(dd->bbox),&(d->data.path.bbox));
return (PyObject*)c;
}
static PyObject *drawf_slice(PyDrawFObject *b,Py_ssize_t i,Py_ssize_t j)
{ PyDrawFObject *c;
Py_ssize_t size,n;
drawfile_diagram *dd;
drawfile_object *d;
if(i<0||j>b->nobjs)
{ PyErr_SetString(PyExc_IndexError,"drawf index out of range");
return NULL;
}
d=findobj(b,i);
size=(char*)findobj(b,j)-(char*)d;
c=new(size);
if(!c) return NULL;
dd=c->drawf;
*((dheader*)dd)=header;
memcpy(dd->objects,d,size);
c->nobjs=j-i;
for(n=j-i;n>0;n--)
{ extend(&(dd->bbox),&(d->data.path.bbox));
d=NEXT(d);
}
return (PyObject*)c;
}
static int drawf_ass_item(PyDrawFObject *b,Py_ssize_t i,PyObject *v)
{ PyErr_SetString(PyExc_IndexError,"drawf ass not implemented");
return NULL;
}
/*{ if(i<0||4*i>=b->length)
{ PyErr_SetString(PyExc_IndexError,"drawf index out of range");
return -1;
}
if(!PyInt_Check(v))
{ PyErr_SetString(PyExc_TypeError,"drawf item must be integer");
return -1;
}
((long*)(b->drawf))[i]=PyInt_AsLong(v);
return 0;
}
*/
static int drawf_ass_slice(PyDrawFObject *b,Py_ssize_t i,Py_ssize_t j,PyObject *v)
{ PyErr_SetString(PyExc_IndexError,"drawf ass_slice not implemented");
return NULL;
}
static PySequenceMethods drawf_as_sequence=
{ (inquiry)drawf_len,
(binaryfunc)drawf_concat,
(ssizeargfunc)drawf_repeat,
(ssizeargfunc)drawf_item,
(ssizessizeargfunc)drawf_slice,
(ssizeobjargproc)drawf_ass_item,
(ssizessizeobjargproc)drawf_ass_slice,
};
static PyObject *PyDrawF_GetAttr(PyDrawFObject *s,char *name)
{
if (!strcmp(name, "size")) return PyInt_FromLong((long)s->size);
if (!strcmp(name, "start")) return PyInt_FromLong((long)s->drawf);
if (!strcmp(name, "__members__"))
{ PyObject *list = PyList_New(2);
if (list)
{ PyList_SetItem(list, 0, PyString_FromString("size"));
PyList_SetItem(list, 1, PyString_FromString("start"));
if (PyErr_Occurred()) { Py_DECREF(list);list = NULL;}
}
return list;
}
return Py_FindMethod(PyDrawF_Methods, (PyObject*) s,name);
}
static void PyDrawF_Dealloc(PyDrawFObject *b)
{
if (b->drawf)
;
else
PyMem_DEL(b->drawf);
PyMem_DEL(b);
}
static PyTypeObject PyDrawFType=
{ PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"drawf", /*tp_name*/
sizeof(PyDrawFObject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)PyDrawF_Dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)PyDrawF_GetAttr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
&drawf_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
static PyMethodDef DrawFMethods[]=
{
{ "load",DrawF_Load,1},
{ "new",DrawF_New,1},
{ NULL,NULL} /* Sentinel */
};
void initdrawf()
{ PyObject *m, *d;
m = Py_InitModule("drawf", DrawFMethods);
d = PyModule_GetDict(m);
DrawFError=PyString_FromString("drawf.error");
PyDict_SetItemString(d,"error",DrawFError);
}