1/* 2 * Several methods of NSBezierPath cannot be handled automaticly because the 3 * size of a C-style array depends on the value of another argument. 4 */ 5#include <Python.h> 6#include "pyobjc-api.h" 7 8#import <AppKit/AppKit.h> 9 10static PyObject* 11call_NSBezierPath_elementAtIndex_associatedPoints_( 12 PyObject* method, 13 PyObject* self, PyObject* arguments) 14{ 15 PyObject* result; 16 PyObject* v; 17 struct objc_super super; 18 int idx; 19 int pointCount; 20 NSPoint points[3]; 21 NSBezierPathElement res; 22 23 if (!PyArg_ParseTuple(arguments, "i", &idx)) { 24 return NULL; 25 } 26 27 PyObjC_DURING 28 if (PyObjCIMP_Check(method)) { 29 res = ((NSBezierPathElement(*)(id,SEL,int,NSPoint*)) 30 PyObjCIMP_GetIMP(method))( 31 PyObjCObject_GetObject(self), 32 PyObjCIMP_GetSelector(method), 33 idx, 34 points 35 ); 36 } else { 37 PyObjC_InitSuper(&super, 38 PyObjCSelector_GetClass(method), 39 PyObjCObject_GetObject(self)); 40 41 42 res = (NSBezierPathElement)objc_msgSendSuper(&super, 43 PyObjCSelector_GetSelector(method), 44 idx, 45 points); 46 } 47 PyObjC_HANDLER 48 PyObjCErr_FromObjC(localException); 49 PyObjC_ENDHANDLER 50 51 if (PyErr_Occurred()) { 52 return NULL; 53 } 54 55 switch (res) { 56 case NSMoveToBezierPathElement: pointCount = 1; break; 57 case NSLineToBezierPathElement: pointCount = 1; break; 58 case NSCurveToBezierPathElement: pointCount = 3; break; 59 case NSClosePathBezierPathElement: pointCount = 0; break; 60 default: 61 PyErr_SetString(PyExc_ValueError, 62 "ObjC returned illegal value"); 63 return NULL; 64 } 65 66 result = PyTuple_New(2); 67 if (result == NULL) return NULL; 68 69 v = PyObjC_ObjCToPython(@encode(NSBezierPathElement), &res); 70 if (v == NULL) { 71 Py_DECREF(result); 72 return NULL; 73 } 74 75 PyTuple_SET_ITEM(result, 0, v); 76 77 v = PyObjC_CArrayToPython(@encode(NSPoint), points, pointCount); 78 if (v == NULL) { 79 Py_DECREF(result); 80 return NULL; 81 } 82 PyTuple_SET_ITEM(result, 1, v); 83 84 return result; 85} 86 87static PyObject* 88call_NSBezierPath_setAssociatedPoints_atIndex_( 89 PyObject* method, 90 PyObject* self, PyObject* arguments) 91{ 92 PyObject* result; 93 struct objc_super super; 94 int idx; 95 NSPoint points[3]; 96 PyObject* pointList; 97 PyObject* seq; 98 int i, len; 99 100 if (!PyArg_ParseTuple(arguments, "Oi", &pointList, &idx)) { 101 return NULL; 102 } 103 104 memset(points, 0, sizeof(points)); 105 106 seq = PySequence_Fast(pointList, "points is not a sequence"); 107 if (seq == NULL) { 108 return NULL; 109 } 110 111 len = PySequence_Fast_GET_SIZE(seq); 112 if (len > 3) { 113 Py_DECREF(seq); 114 PyErr_SetString(PyExc_ValueError, "Need at most 3 elements"); 115 return NULL; 116 } 117 118 for (i = 0; i < len; i++) { 119 int err = PyObjC_PythonToObjC(@encode(NSPoint), 120 PySequence_Fast_GET_ITEM(seq, i), points + i); 121 if (err == -1) { 122 return NULL; 123 } 124 } 125 126 PyObjC_DURING 127 if (PyObjCIMP_Check(method)) { 128 ((void(*)(id,SEL,NSPoint*,int)) 129 PyObjCIMP_GetIMP(method))( 130 PyObjCObject_GetObject(self), 131 PyObjCIMP_GetSelector(method), 132 points, 133 idx); 134 } else { 135 PyObjC_InitSuper(&super, 136 PyObjCSelector_GetClass(method), 137 PyObjCObject_GetObject(self)); 138 139 140 (void)objc_msgSendSuper(&super, 141 PyObjCSelector_GetSelector(method), 142 points, 143 idx); 144 } 145 PyObjC_HANDLER 146 PyObjCErr_FromObjC(localException); 147 result = NULL; 148 PyObjC_ENDHANDLER 149 150 if (PyErr_Occurred()) return NULL; 151 152 result = Py_None; 153 Py_INCREF(result); 154 155 return result; 156} 157 158static void 159imp_NSBezierPath_elementAtIndex_associatedPoints_( 160 void* cif __attribute__((__unused__)), 161 void* resp, 162 void** args, 163 void* callable) 164{ 165 id self = *(id*)args[0]; 166 //SEL _meth = *(SEL*)args[1]; 167 int idx = *(int*)args[2]; 168 NSPoint* points = *(NSPoint**)args[3]; 169 170 PyObject* result; 171 PyObject* seq = NULL; 172 PyObject* arglist = NULL; 173 PyObject* v; 174 int err; 175 int pointCount; 176 int i; 177 PyObject* pyself = NULL; 178 int cookie = 0; 179 180 PyGILState_STATE state = PyGILState_Ensure(); 181 182 arglist = PyTuple_New(2); 183 if (arglist == NULL) goto error; 184 185 pyself = PyObjCObject_NewTransient(self, &cookie); 186 if (pyself == NULL) goto error; 187 PyTuple_SetItem(arglist, 0, pyself); 188 Py_INCREF(pyself); 189 190 v = PyInt_FromLong(idx); 191 if (v == NULL) goto error; 192 PyTuple_SET_ITEM(arglist, 1, v); 193 194 result = PyObject_Call((PyObject*)callable, arglist, NULL); 195 Py_DECREF(arglist); arglist = NULL; 196 PyObjCObject_ReleaseTransient(pyself, cookie); pyself = NULL; 197 if (result == NULL) goto error; 198 199 seq = PySequence_Fast(result, "should return tuple of lenght 2"); 200 Py_DECREF(result); 201 if (seq == NULL) goto error; 202 203 if (PySequence_Fast_GET_SIZE(seq) != 2) { 204 PyErr_SetString(PyExc_ValueError, 205 "should return tuple of lenght 2"); 206 goto error; 207 } 208 209 v = PySequence_Fast_GET_ITEM(seq, 0); 210 211 err = PyObjC_PythonToObjC(@encode(NSBezierPathElement), v, resp); 212 if (err == -1) goto error; 213 214 v = PySequence_Fast(PySequence_Fast_GET_ITEM(seq, 1), 215 "result[1] should be a sequence"); 216 if (v == NULL) goto error; 217 218 switch (*(NSBezierPathElement*)resp) { 219 case NSMoveToBezierPathElement: pointCount = 1; break; 220 case NSLineToBezierPathElement: pointCount = 1; break; 221 case NSCurveToBezierPathElement: pointCount = 3; break; 222 case NSClosePathBezierPathElement: pointCount = 0; break; 223 default: 224 PyErr_SetString(PyExc_ValueError, 225 "Return[0] should be NS{*}PathElement"); 226 Py_DECREF(v); 227 goto error; 228 } 229 230 if (PySequence_Fast_GET_SIZE(v) != pointCount) { 231 PyErr_SetString(PyExc_ValueError, 232 "wrong number of points"); 233 Py_DECREF(v); 234 goto error; 235 } 236 237 for (i = 0; i < pointCount; i++) { 238 err = PyObjC_PythonToObjC(@encode(NSPoint), 239 PySequence_Fast_GET_ITEM(v, i), 240 points + i); 241 if (err == -1) { 242 Py_DECREF(v); 243 goto error; 244 } 245 } 246 247 Py_DECREF(v); 248 Py_DECREF(seq); 249 PyGILState_Release(state); 250 return; 251 252error: 253 *(NSBezierPathElement*)resp = 0; 254 Py_XDECREF(arglist); 255 if (pyself) { 256 PyObjCObject_ReleaseTransient(pyself, cookie); 257 } 258 Py_XDECREF(seq); 259 PyObjCErr_ToObjCWithGILState(&state); 260} 261 262 263static PyMethodDef mod_methods[] = { 264 { 0, 0, 0, 0 } /* sentinel */ 265}; 266 267void init_nsbezierpath(void); 268void init_nsbezierpath(void) 269{ 270 PyObject* m = Py_InitModule4("_nsbezierpath", mod_methods, "", NULL, 271 PYTHON_API_VERSION); 272 273 PyObjC_ImportAPI(m); 274 275 Class cls = objc_lookUpClass("NSBezierPath"); 276 if (!cls) return; 277 278 if (PyObjC_RegisterMethodMapping(cls, 279 @selector(elementAtIndex:associatedPoints:), 280 call_NSBezierPath_elementAtIndex_associatedPoints_, 281 imp_NSBezierPath_elementAtIndex_associatedPoints_) < 0 ) { 282 283 return; 284 } 285 286 if (PyObjC_RegisterMethodMapping(cls, 287 @selector(setAssociatedPoints:atIndex:), 288 call_NSBezierPath_setAssociatedPoints_atIndex_, 289 PyObjCUnsupportedMethod_IMP) < 0 ) { 290 291 return; 292 } 293 294 return; 295} 296