1 /* drawf DrawFile functions */
4 #include "oslib/osfile.h"
5 #include "oslib/drawfile.h"
10 #define PyDrawF_Check(op) ((op)->ob_type == &PyDrawFType)
13 #define DRAWTYPE 0xaff
14 #define NEXT(d) ((drawfile_object*)((char*)(d)+(d)->size))
18 drawfile_diagram
*drawf
;
19 int size
; /*length in bytes*/
20 int nobjs
; /* no of objects */
23 typedef struct dheader
31 static PyObject
*DrawFError
; /* Exception drawf.error */
33 static PyTypeObject PyDrawFType
;
35 static dheader header
=
38 {'P','y','t','h','o','n',' ',' ',' ',' ',' ',' '},
39 {INT_MAX
,INT_MAX
,INT_MIN
,INT_MIN
}
42 static PyObject
*drawf_oserror(void)
43 { PyErr_SetString(DrawFError
,e
->errmess
);
47 static PyObject
*drawf_error(char *s
)
48 { PyErr_SetString(DrawFError
,s
);
52 /* DrawFile commands */
54 static void countobjs(PyDrawFObject
*pd
)
56 drawfile_diagram
*dd
=pd
->drawf
;
57 drawfile_object
*d
=dd
->objects
;
58 char *end
=(char*)dd
+pd
->size
;
63 if(q
<=0||q
&3) return ;
66 if ((char*)d
==end
) pd
->nobjs
=k
;
69 static drawfile_object
*findobj(PyDrawFObject
*pd
,Py_ssize_t n
)
70 { drawfile_diagram
*dd
=pd
->drawf
;
71 drawfile_object
*d
=dd
->objects
;
72 for(;n
>0;n
--) d
=NEXT(d
);
76 static PyDrawFObject
* new(int size
)
77 { PyDrawFObject
*b
=PyObject_NEW(PyDrawFObject
,&PyDrawFType
);
80 b
->drawf
=malloc(size
);
83 return (PyDrawFObject
*)PyErr_NoMemory();
89 static void extend(os_box
*b
,os_box
*c
)
90 { if(b
->x0
>c
->x0
) b
->x0
=c
->x0
;
91 if(b
->y0
>c
->y0
) b
->y0
=c
->y0
;
92 if(b
->x1
<c
->x1
) b
->x1
=c
->x1
;
93 if(b
->y1
<c
->y1
) b
->y1
=c
->y1
;
96 static PyObject
*DrawF_New(PyObject
*self
,PyObject
*args
)
98 if(!PyArg_ParseTuple(args
,"")) return NULL
;
101 *((dheader
*)b
->drawf
)=header
;
103 return (PyObject
*)b
;
106 static PyObject
*DrawF_Load(PyObject
*self
,PyObject
*args
)
110 fileswitch_object_type ot
;
111 if(!PyArg_ParseTuple(args
,"s",&fname
)) return NULL
;
112 e
=xosfile_read_no_path(fname
,&ot
,0,0,&size
,0);
113 if(e
) return drawf_oserror();
115 if(ot
!=osfile_IS_FILE
||size
<0||size
&3) return drawf_error("Bad draw file");
118 e
=xosfile_load_stamped_no_path(fname
,(byte
*)(b
->drawf
),0,0,0,0,0);
121 return drawf_oserror();
124 if(b
->nobjs
>=0) return (PyObject
*)b
;
126 return drawf_error("Corrupt draw file");
130 static PyObject
*DrawF_Save(PyDrawFObject
*self
,PyObject
*arg
)
132 if(!PyArg_ParseTuple(arg
,"s",&fname
)) return NULL
;
133 e
=xosfile_save_stamped(fname
,DRAWTYPE
,
134 (byte
*)(self
->drawf
),(byte
*)(self
->drawf
)+self
->size
);
135 if (e
) return drawf_oserror();
136 Py_INCREF(Py_None
);return Py_None
;
139 static PyObject
*DrawF_Render(PyDrawFObject
*self
,PyObject
*arg
)
140 { int flags
,trans
,clip
,flat
;
141 if(!PyArg_ParseTuple(arg
,"iiii",&flags
,&trans
,&clip
,&flat
)) return NULL
;
142 e
=xdrawfile_render((drawfile_render_flags
)flags
,self
->drawf
,self
->size
,
143 (os_trfm
*)trans
,(os_box
*)clip
,flat
);
144 if(e
) return drawf_oserror();
145 Py_INCREF(Py_None
);return Py_None
;
148 static PyObject
*DrawF_Path(PyDrawFObject
*self
,PyObject
*arg
)
154 drawfile_path_style style
;
156 int n
,i
,element_count
;
157 drawfile_diagram
*diag
;
158 drawfile_object
*dobj
;
159 drawfile_path
*dpath
;
161 draw_line_style line_style
;
162 draw_dash_pattern
*dash_pattern
=0;
165 if(!PyArg_ParseTuple(arg
,"O!(iiii)|O!i",&PyList_Type
,&pl
,(int*)&fill
,
166 (int*)&outline
,&width
,(int*)&style
,&PyTuple_Type
,&dp
,&start
)) return NULL
;
168 { element_count
=PyTuple_Size(dp
);
169 size
+=4*element_count
+8;
170 style
.flags
|=drawfile_PATH_DASHED
;
172 else style
.flags
&=~drawfile_PATH_DASHED
;
175 for(i
=0;i
<n
;i
++) if(!PyInt_Check(PyList_GetItem(pl
,i
))) size
+=4;
176 diag
=realloc(self
->drawf
,self
->size
+size
);
177 if(!diag
) return PyErr_NoMemory();
179 dobj
=(drawfile_object
*)((char*)diag
+self
->size
);
180 dobj
->type
=drawfile_TYPE_PATH
;
182 dpath
=&dobj
->data
.path
;
186 dpath
->fill
=fill
;dpath
->outline
=outline
;
187 dpath
->width
=width
;dpath
->style
=style
;
188 pe
=(long*)&(dpath
->path
);
190 { dash_pattern
=&(((drawfile_path_with_pattern
*)dpath
)->pattern
);
191 dash_pattern
->start
=start
;
192 dash_pattern
->element_count
=element_count
;
193 for(i
=0;i
<element_count
;i
++)
194 { dash_pattern
->elements
[i
]=(int)PyInt_AsLong(PyTuple_GetItem(dp
,i
));
198 thepath
=(draw_path
*)pe
;
201 { PyObject
*p
=PyList_GetItem(pl
,i
);
203 *pe
++=PyInt_AsLong(p
);
206 *pe
++=PyInt_AsLong(PyTuple_GetItem(p
,0));
207 *pe
++=PyInt_AsLong(PyTuple_GetItem(p
,1));
211 line_style
.join_style
=style
.flags
&3;
212 line_style
.end_cap_style
=(style
.flags
&3)>>2;
213 line_style
.start_cap_style
=(style
.flags
&3)>>4;
214 line_style
.reserved
=0;
215 line_style
.mitre_limit
=10;
216 line_style
.start_cap_width
=style
.cap_width
;
217 line_style
.end_cap_width
=style
.cap_width
;
218 line_style
.start_cap_length
=style
.cap_length
;
219 line_style
.end_cap_length
=style
.cap_length
;
220 e
=xdraw_process_path(thepath
,0x70000000,0,0,width
,&line_style
,dash_pattern
,
221 (draw_output_path
)((char*)box
+0x80000000),0);
222 if(e
) return drawf_oserror();
224 /* draw_process_path seems to have a bug:
225 If the bounding box size is zero, it returns 0x7FFFFFFF, ..., 0x80000000 instead of the
227 if (box
->x0
==0x7FFFFFFF)
229 /* path has zero extension, so forget it; it would be invisible anyway */
232 diag
=realloc(self
->drawf
,self
->size
);
233 if(!diag
) return PyErr_NoMemory();
237 extend(&(diag
->bbox
),box
);
238 Py_INCREF(Py_None
);return Py_None
;
241 static PyObject
*DrawF_Text(PyDrawFObject
*self
,PyObject
*arg
)
242 { os_colour fill
,bg_hint
;
243 drawfile_text_style style
;
247 drawfile_diagram
*diag
;
248 drawfile_object
*dobj
;
249 drawfile_text
*dtext
;
251 if(!PyArg_ParseTuple(arg
,"(ii)s(iiiii)",&x
,&y
,&text
,
252 (int*)&fill
,(int*)&bg_hint
,(int*)&style
,&xsize
,&ysize
)) return NULL
;
254 size
=((len
+4)&(~3))+52;
255 diag
=realloc(self
->drawf
,self
->size
+size
);
256 if(!diag
) return PyErr_NoMemory();
258 dobj
=(drawfile_object
*)((char*)diag
+self
->size
);
259 dobj
->type
=drawfile_TYPE_TEXT
;
261 dtext
=&dobj
->data
.text
;
265 dtext
->bg_hint
=bg_hint
;
271 memset(dtext
->text
,0,(len
+4)&(~3));
272 sprintf(dtext
->text
,"%s",text
);
274 box
->x0
=x
;box
->y0
=y
;box
->x1
=x
+len
*xsize
;box
->y1
=y
+ysize
;
275 extend(&(diag
->bbox
),box
);
276 Py_INCREF(Py_None
);return Py_None
;
279 static PyObject
*DrawF_TText(PyDrawFObject
*self
,PyObject
*arg
)
280 { os_colour fill
,bg_hint
;
281 drawfile_text_style style
;
283 int t1
,t2
,t3
,t4
,t5
,t6
;
286 drawfile_diagram
*diag
;
287 drawfile_object
*dobj
;
288 drawfile_trfm_text
*dtext
;
293 if(!PyArg_ParseTuple(arg
,"(ii)s(iiiii)|(iiiiii)",&x
,&y
,&text
,
294 (int*)&fill
,(int*)&bg_hint
,(int*)&style
,&xsize
,&ysize
,&t1
,&t2
,&t3
,&t4
,&t5
,&t6
)) return NULL
;
296 size
=((len
+4)&(~3))+52+28;
297 diag
=realloc(self
->drawf
,self
->size
+size
);
298 if(!diag
) return PyErr_NoMemory();
300 dobj
=(drawfile_object
*)((char*)diag
+self
->size
);
301 dobj
->type
=drawfile_TYPE_TRFM_TEXT
;
303 dtext
=&dobj
->data
.trfm_text
;
306 dtext
->trfm
.entries
[0][0]=t1
;
307 dtext
->trfm
.entries
[0][1]=t2
;
308 dtext
->trfm
.entries
[1][0]=t3
;
309 dtext
->trfm
.entries
[1][1]=t4
;
310 dtext
->trfm
.entries
[2][0]=t5
;
311 dtext
->trfm
.entries
[2][1]=t6
;
314 dtext
->bg_hint
=bg_hint
;
320 memset(dtext
->text
,0,(len
+4)&(~3));
321 sprintf(dtext
->text
,"%s",text
);
323 box
->x0
=x
;box
->y0
=y
;box
->x1
=x
+len
*xsize
;box
->y1
=y
+ysize
;
324 extend(&(diag
->bbox
),box
);
325 Py_INCREF(Py_None
);return Py_None
;
328 static PyObject
*DrawF_FontTable(PyDrawFObject
*self
,PyObject
*arg
)
330 PyObject
*d
,*key
,*value
;
331 drawfile_diagram
*diag
;
332 drawfile_object
*dobj
;
334 if(!PyArg_ParseTuple(arg
,"O!",&PyDict_Type
,&d
)) return NULL
;
335 while(PyDict_Next(d
,&n
,&key
,&value
))
336 { int m
=PyString_Size(value
);
337 if(m
<0||!PyInt_Check(key
)) return NULL
;
341 diag
=realloc(self
->drawf
,self
->size
+size
);
342 if(!diag
) return PyErr_NoMemory();
344 dobj
=(drawfile_object
*)((char*)diag
+self
->size
);
345 dobj
->type
=drawfile_TYPE_FONT_TABLE
;
347 dtable
=(char*)(&dobj
->data
.font_table
);
350 memset(dtable
,0,size
-8);
352 while(PyDict_Next(d
,&n
,&key
,&value
))
353 { int m
=PyString_Size(value
);
354 *dtable
=(char)PyInt_AsLong(key
);
355 strcpy(dtable
+1,PyString_AsString(value
));
358 Py_INCREF(Py_None
);return Py_None
;
361 static PyObject
*DrawF_Group(PyDrawFObject
*self
,PyObject
*arg
)
365 drawfile_diagram
*diag
;
366 drawfile_object
*dobj
;
367 drawfile_group
*dgroup
;
368 if(!PyArg_ParseTuple(arg
,"O!|s",&PyDrawFType
,(PyObject
*)&g
,&name
))
371 diag
=realloc(self
->drawf
,self
->size
+size
);
372 if(!diag
) return PyErr_NoMemory();
375 dobj
=(drawfile_object
*)((char*)diag
+self
->size
);
377 dobj
->type
=drawfile_TYPE_GROUP
;
378 dobj
->size
=g
->size
-4;
379 dgroup
=&dobj
->data
.group
;
380 dgroup
->bbox
=g
->drawf
->bbox
;
381 memset(dgroup
->name
,' ',12);
384 memcpy(dgroup
->name
,name
,n
);
385 memcpy((char*)dgroup
->objects
,(char*)g
->drawf
+40,g
->size
-40);
386 extend(&(diag
->bbox
),&(dgroup
->bbox
));
387 Py_INCREF(Py_None
);return Py_None
;
390 static PyObject
*DrawF_Find(PyDrawFObject
*self
,PyObject
*arg
)
394 if(!PyArg_ParseTuple(arg
,"ii|i",&x
,&y
,&n
)) return NULL
;
395 if(n
<self
->nobjs
&&n
>=0)
398 { if(x
>=d
->data
.text
.bbox
.x0
&&x
<=d
->data
.text
.bbox
.x1
&&
399 y
>=d
->data
.text
.bbox
.y0
&&y
<=d
->data
.text
.bbox
.y1
) { r
=n
;break;}
404 return PyInt_FromLong(r
);
408 static PyObject
*DrawF_Box(PyDrawFObject
*self
,PyObject
*arg
)
411 if(!PyArg_ParseTuple(arg
,"|i",&n
)) return NULL
;
412 if(n
>=self
->nobjs
|n
<0) box
=&(self
->drawf
->bbox
);
413 else box
=&(findobj(self
,n
)->data
.text
.bbox
);
414 return Py_BuildValue("iiii",box
->x0
,box
->y0
,box
->x1
,box
->y1
);
417 static void SetBlock(drawfile_object
*d
,int size
,int type
,int offset
,int value
)
418 { char *end
=(char*)d
+size
;
419 printf("s%d t%d o%d v%d\n",size
,type
,offset
,value
);
420 for(;(char*)d
<end
;d
=NEXT(d
))
421 if(d
->type
==type
) ((int*)(d
))[offset
]=value
;
422 else if(d
->type
==drawfile_TYPE_GROUP
)
423 SetBlock((drawfile_object
*)&d
->data
.group
.objects
,
424 d
->size
,type
,offset
,value
);
425 printf("SetBlock Done\n");
428 static PyObject
*SetWord(PyDrawFObject
*self
,PyObject
*arg
,int type
,int offset
)
429 { int n
=PyTuple_Size(arg
);
432 drawfile_object
*e
,*d
=self
->drawf
->objects
;
433 if(n
==0) return drawf_error("Value Required");
434 par
=PyTuple_GetItem(arg
,0);
435 if(!PyInt_Check(par
))
436 { PyErr_SetString(PyExc_TypeError
,"Int Required");
439 value
=(int)PyInt_AsLong(par
);
440 if(n
==1) SetBlock(d
,self
->size
-HDRSIZE
,type
,offset
,value
);
443 { par
=PyTuple_GetItem(arg
,m
);
444 if(!PyInt_Check(par
))
445 { PyErr_SetString(PyExc_TypeError
,"Int Required");
448 q
=(int)PyInt_AsLong(par
);
449 if(q
<0||q
>=self
->nobjs
)
450 { PyErr_SetString(PyExc_ValueError
,"Object out of range");
454 for(;q
>0;q
--) e
=NEXT(e
);
456 { ((int*)(e
))[offset
]=value
;
458 else if(e
->type
==drawfile_TYPE_GROUP
)
459 SetBlock((drawfile_object
*)&e
->data
.group
.objects
,
460 e
->size
-GRPHDRSIZE
,type
,offset
,value
);
463 Py_INCREF(Py_None
);return Py_None
;
466 static PyObject
*DrawF_PathFill(PyDrawFObject
*self
,PyObject
*arg
)
467 { return SetWord(self
,arg
,drawfile_TYPE_PATH
,6);
470 static PyObject
*DrawF_PathColour(PyDrawFObject
*self
,PyObject
*arg
)
471 { return SetWord(self
,arg
,drawfile_TYPE_PATH
,7);
474 static PyObject
*DrawF_TextColour(PyDrawFObject
*self
,PyObject
*arg
)
475 { return SetWord(self
,arg
,drawfile_TYPE_TEXT
,6);
478 static PyObject
*DrawF_TextBackground(PyDrawFObject
*self
,PyObject
*arg
)
479 { return SetWord(self
,arg
,drawfile_TYPE_TEXT
,7);
482 static struct PyMethodDef PyDrawF_Methods
[]=
484 { "render",(PyCFunction
)DrawF_Render
,1},
485 { "save",(PyCFunction
)DrawF_Save
,1},
486 { "path",(PyCFunction
)DrawF_Path
,1},
487 { "text",(PyCFunction
)DrawF_Text
,1},
488 { "ttext",(PyCFunction
)DrawF_TText
,1},
489 { "fonttable",(PyCFunction
)DrawF_FontTable
,1},
490 { "group",(PyCFunction
)DrawF_Group
,1},
491 { "find",(PyCFunction
)DrawF_Find
,1},
492 { "box",(PyCFunction
)DrawF_Box
,1},
493 { "pathfill",(PyCFunction
)DrawF_PathFill
,1},
494 { "pathcolour",(PyCFunction
)DrawF_PathColour
,1},
495 { "textcolour",(PyCFunction
)DrawF_TextColour
,1},
496 { "textbackground",(PyCFunction
)DrawF_TextBackground
,1},
497 { NULL
,NULL
} /* sentinel */
500 static int drawf_len(PyDrawFObject
*b
)
504 static PyObject
*drawf_concat(PyDrawFObject
*b
,PyDrawFObject
*c
)
505 { int size
=b
->size
+c
->size
-2*HDRSIZE
;
506 PyDrawFObject
*p
=new(size
);
507 drawfile_diagram
*dd
;
512 d
=(drawfile_object
*)((char*)dd
+b
->size
);
513 memcpy((char*)dd
,(char*)(b
->drawf
),b
->size
);
514 memcpy(d
,(char*)(c
->drawf
)+HDRSIZE
,c
->size
-HDRSIZE
);
515 p
->nobjs
=b
->nobjs
+c
->nobjs
;
516 for(n
=c
->nobjs
;n
>0;n
--)
517 { extend(&(dd
->bbox
),&(d
->data
.path
.bbox
));
523 static PyObject
*drawf_repeat(PyDrawFObject
*b
,Py_ssize_t i
)
524 { PyErr_SetString(PyExc_IndexError
,"drawf repetition not implemented");
528 static PyObject
*drawf_item(PyDrawFObject
*b
,Py_ssize_t i
)
531 drawfile_diagram
*dd
;
534 { PyErr_SetString(PyExc_IndexError
,"drawf index out of range");
538 size
=(char*)findobj(b
,i
+1)-(char*)d
;
542 *((dheader
*)dd
)=header
;
543 memcpy(dd
->objects
,d
,size
);
545 extend(&(dd
->bbox
),&(d
->data
.path
.bbox
));
549 static PyObject
*drawf_slice(PyDrawFObject
*b
,Py_ssize_t i
,Py_ssize_t j
)
552 drawfile_diagram
*dd
;
555 { PyErr_SetString(PyExc_IndexError
,"drawf index out of range");
559 size
=(char*)findobj(b
,j
)-(char*)d
;
563 *((dheader
*)dd
)=header
;
564 memcpy(dd
->objects
,d
,size
);
567 { extend(&(dd
->bbox
),&(d
->data
.path
.bbox
));
573 static int drawf_ass_item(PyDrawFObject
*b
,Py_ssize_t i
,PyObject
*v
)
574 { PyErr_SetString(PyExc_IndexError
,"drawf ass not implemented");
577 /*{ if(i<0||4*i>=b->length)
578 { PyErr_SetString(PyExc_IndexError,"drawf index out of range");
582 { PyErr_SetString(PyExc_TypeError,"drawf item must be integer");
585 ((long*)(b->drawf))[i]=PyInt_AsLong(v);
590 static int drawf_ass_slice(PyDrawFObject
*b
,Py_ssize_t i
,Py_ssize_t j
,PyObject
*v
)
591 { PyErr_SetString(PyExc_IndexError
,"drawf ass_slice not implemented");
595 static PySequenceMethods drawf_as_sequence
=
596 { (inquiry
)drawf_len
,
597 (binaryfunc
)drawf_concat
,
598 (ssizeargfunc
)drawf_repeat
,
599 (ssizeargfunc
)drawf_item
,
600 (ssizessizeargfunc
)drawf_slice
,
601 (ssizeobjargproc
)drawf_ass_item
,
602 (ssizessizeobjargproc
)drawf_ass_slice
,
605 static PyObject
*PyDrawF_GetAttr(PyDrawFObject
*s
,char *name
)
607 if (!strcmp(name
, "size")) return PyInt_FromLong((long)s
->size
);
608 if (!strcmp(name
, "start")) return PyInt_FromLong((long)s
->drawf
);
609 if (!strcmp(name
, "__members__"))
610 { PyObject
*list
= PyList_New(2);
612 { PyList_SetItem(list
, 0, PyString_FromString("size"));
613 PyList_SetItem(list
, 1, PyString_FromString("start"));
614 if (PyErr_Occurred()) { Py_DECREF(list
);list
= NULL
;}
618 return Py_FindMethod(PyDrawF_Methods
, (PyObject
*) s
,name
);
621 static void PyDrawF_Dealloc(PyDrawFObject
*b
)
630 static PyTypeObject PyDrawFType
=
631 { PyObject_HEAD_INIT(&PyType_Type
)
634 sizeof(PyDrawFObject
), /*tp_size*/
637 (destructor
)PyDrawF_Dealloc
, /*tp_dealloc*/
639 (getattrfunc
)PyDrawF_GetAttr
, /*tp_getattr*/
644 &drawf_as_sequence
, /*tp_as_sequence*/
651 static PyMethodDef DrawFMethods
[]=
653 { "load",DrawF_Load
,1},
654 { "new",DrawF_New
,1},
655 { NULL
,NULL
} /* Sentinel */
660 m
= Py_InitModule("drawf", DrawFMethods
);
661 d
= PyModule_GetDict(m
);
662 DrawFError
=PyString_FromString("drawf.error");
663 PyDict_SetItemString(d
,"error",DrawFError
);