1/* 2 * Manual wrappers for CoreGraphics 3 */ 4#include <Python.h> 5#include "pyobjc-api.h" 6 7#import <ApplicationServices/ApplicationServices.h> 8 9#ifndef OS_TIGER 10static PyObject* 11m_CGFontCopyTableTags(PyObject* self __attribute__((__unused__)), 12 PyObject* args) 13{ 14 PyObject* py_font; 15 CGFontRef font; 16 CFArrayRef tags; 17 18 if (!PyArg_ParseTuple(args, "O", &py_font)) { 19 return NULL; 20 } 21 22 if (PyObjC_PythonToObjC(@encode(CGFontRef), py_font, &font) == -1) { 23 return NULL; 24 } 25 26 tags = NULL; 27 PyObjC_DURING 28 tags = CGFontCopyTableTags(font); 29 30 PyObjC_HANDLER 31 tags = NULL; 32 PyObjCErr_FromObjC(localException); 33 PyObjC_ENDHANDLER 34 35 if (tags == NULL && PyErr_Occurred()) { 36 return NULL; 37 } 38 39 if (tags == NULL) { 40 Py_INCREF(Py_None); 41 return Py_None; 42 } 43 44 Py_ssize_t len = CFArrayGetCount(tags); 45 Py_ssize_t i; 46 PyObject* result = PyTuple_New(len); 47 if (result == NULL) { 48 CFRelease(tags); 49 return NULL; 50 } 51 52 for (i = 0; i < len; i++) { 53 uint32_t cur = (uint32_t)(uintptr_t)CFArrayGetValueAtIndex(tags, i); 54 PyObject* v = PyObjC_ObjCToPython(@encode(uint32_t), &cur); 55 if (v == NULL) { 56 CFRelease(tags); 57 return NULL; 58 } 59 PyTuple_SET_ITEM(result, i, v); 60 } 61 CFRelease(tags); 62 return result; 63} 64 65static PyObject* 66m_CGWindowListCreate(PyObject* self __attribute__((__unused__)), 67 PyObject* args) 68{ 69 PyObject* py_option; 70 PyObject* py_relativeToWindow; 71 CGWindowListOption option; 72 CGWindowID relativeToWindow; 73 CFArrayRef windowList; 74 75 if (!PyArg_ParseTuple(args, "OO", &py_option, &py_relativeToWindow)) { 76 return NULL; 77 } 78 79 if (PyObjC_PythonToObjC(@encode(CGWindowListOption), py_option, &option) == -1) { 80 return NULL; 81 } 82 83 if (PyObjC_PythonToObjC(@encode(CGWindowID), py_relativeToWindow, &relativeToWindow) == -1) { 84 return NULL; 85 } 86 87 windowList = NULL; 88 PyObjC_DURING 89 windowList = CGWindowListCreate(option, relativeToWindow); 90 91 PyObjC_HANDLER 92 windowList = NULL; 93 PyObjCErr_FromObjC(localException); 94 PyObjC_ENDHANDLER 95 96 if (windowList == NULL && PyErr_Occurred()) { 97 return NULL; 98 } 99 100 if (windowList == NULL) { 101 Py_INCREF(Py_None); 102 return Py_None; 103 } 104 105 Py_ssize_t len = CFArrayGetCount(windowList); 106 Py_ssize_t i; 107 PyObject* result = PyTuple_New(len); 108 if (result == NULL) { 109 CFRelease(windowList); 110 return NULL; 111 } 112 113 for (i = 0; i < len; i++) { 114 CGWindowID cur = (CGWindowID)CFArrayGetValueAtIndex(windowList, i); 115 PyObject* v = PyObjC_ObjCToPython(@encode(CGWindowID), &cur); 116 if (v == NULL) { 117 CFRelease(windowList); 118 return NULL; 119 } 120 PyTuple_SET_ITEM(result, i, v); 121 } 122 CFRelease(windowList); 123 return result; 124} 125 126 127 128static CFArrayRef 129createWindowList(PyObject* items) 130{ 131 PyObject* seq = PySequence_Fast(items, "list of windowIDs"); 132 if (seq == NULL) { 133 return NULL; 134 } 135 136 CFMutableArrayRef array = CFArrayCreateMutable(NULL, PySequence_Fast_GET_SIZE(seq), NULL); 137 if (array == NULL) { 138 Py_DECREF(seq); 139 PyErr_SetString(PyExc_ValueError, "Cannot create CFArray"); 140 return NULL; 141 } 142 143 Py_ssize_t len = PySequence_Fast_GET_SIZE(seq); 144 Py_ssize_t i; 145 for (i = 0; i < len; i++) { 146 CGWindowID windowID; 147 148 if (PyObjC_PythonToObjC(@encode(CGWindowID), PySequence_Fast_GET_ITEM(seq, i), &windowID) == -1) { 149 Py_DECREF(seq); 150 CFRelease(array); 151 return NULL; 152 } 153 CFArrayAppendValue(array, (const void*)windowID); 154 } 155 Py_DECREF(seq); 156 return (CFArrayRef)array; 157} 158 159static PyObject* 160m_CGWindowListCreateDescriptionFromArray(PyObject* self __attribute__((__unused__)), 161 PyObject* args) 162{ 163 PyObject* py_windowArray; 164 CFArrayRef windowArray; 165 166 if (!PyArg_ParseTuple(args, "O", &py_windowArray)) { 167 return NULL; 168 } 169 170 windowArray = createWindowList(py_windowArray); 171 if (windowArray == NULL) { 172 return NULL; 173 } 174 175 CFArrayRef descriptions = NULL; 176 PyObjC_DURING 177 descriptions = CGWindowListCreateDescriptionFromArray(windowArray); 178 179 PyObjC_HANDLER 180 descriptions = NULL; 181 PyObjCErr_FromObjC(localException); 182 PyObjC_ENDHANDLER 183 184 CFRelease(windowArray); 185 186 if (descriptions == NULL && PyErr_Occurred()) { 187 return NULL; 188 } 189 190 if (descriptions == NULL) { 191 Py_INCREF(Py_None); 192 return Py_None; 193 } 194 195 PyObject* rv = PyObjC_ObjCToPython(@encode(CFArrayRef), &descriptions); 196 CFRelease(descriptions); 197 return rv; 198} 199 200static PyObject* 201m_CGWindowListCreateImageFromArray(PyObject* self __attribute__((__unused__)), 202 PyObject* args) 203{ 204 PyObject* py_screenBounds; 205 PyObject* py_windowArray; 206 PyObject* py_imageOption; 207 CGRect screenBounds; 208 CFArrayRef windowArray; 209 CGWindowImageOption imageOption; 210 211 if (!PyArg_ParseTuple(args, "OOO", &py_screenBounds, &py_windowArray, &py_imageOption)) { 212 return NULL; 213 } 214 215 if (PyObjC_PythonToObjC(@encode(CGRect), py_screenBounds, &screenBounds) == -1) { 216 return NULL; 217 } 218 219 if (PyObjC_PythonToObjC(@encode(CGWindowImageOption), py_imageOption, &imageOption) == -1) { 220 return NULL; 221 } 222 223 224 windowArray = createWindowList(py_windowArray); 225 if (windowArray == NULL) { 226 return NULL; 227 } 228 229 CGImageRef image = NULL; 230 PyObjC_DURING 231 image = CGWindowListCreateImageFromArray(screenBounds, windowArray, imageOption); 232 233 PyObjC_HANDLER 234 image = NULL; 235 PyObjCErr_FromObjC(localException); 236 PyObjC_ENDHANDLER 237 238 CFRelease(windowArray); 239 240 if (image == NULL && PyErr_Occurred()) { 241 return NULL; 242 } 243 244 if (image == NULL) { 245 Py_INCREF(Py_None); 246 return Py_None; 247 } 248 249 PyObject* rv = PyObjC_ObjCToPython(@encode(CGImageRef), &image); 250 CFRelease(image); 251 return rv; 252} 253#endif /* !OS_TIGER */ 254 255static PyObject* 256m_CGBitmapContextCreate(PyObject* self __attribute__((__unused__)), 257 PyObject* args) 258{ 259 PyObject* py_data; 260 PyObject* py_width; 261 PyObject* py_height; 262 PyObject* py_bitsPerComponent; 263 PyObject* py_bytesPerRow; 264 PyObject* py_colorSpace; 265 PyObject* py_bitmapInfo; 266 267 void* data; 268 size_t width; 269 size_t height; 270 size_t bitsPerComponent; 271 size_t bytesPerRow; 272 CGColorSpaceRef colorSpace; 273 CGBitmapInfo bitmapInfo; 274 275 if (!PyArg_ParseTuple(args, "OOOOOOO", &py_data, &py_width, &py_height, &py_bitsPerComponent, &py_bytesPerRow, &py_colorSpace, &py_bitmapInfo)) { 276 return NULL; 277 } 278 279 if (PyObjC_PythonToObjC(@encode(size_t), py_width, &width) == -1) { 280 return NULL; 281 } 282 if (PyObjC_PythonToObjC(@encode(size_t), py_height, &height) == -1) { 283 return NULL; 284 } 285 if (PyObjC_PythonToObjC(@encode(size_t), py_bitsPerComponent, &bitsPerComponent) == -1) { 286 return NULL; 287 } 288 if (PyObjC_PythonToObjC(@encode(size_t), py_bytesPerRow, &bytesPerRow) == -1) { 289 return NULL; 290 } 291 if (PyObjC_PythonToObjC(@encode(CGColorSpaceRef), py_colorSpace, &colorSpace) == -1) { 292 return NULL; 293 } 294 if (PyObjC_PythonToObjC(@encode(CGBitmapInfo), py_bitmapInfo, &bitmapInfo) == -1) { 295 return NULL; 296 } 297 298 if (py_data == Py_None) { 299 data = NULL; 300 301 } else if (PyUnicode_Check(py_data)) { 302 PyErr_SetString(PyExc_TypeError, "Cannot use Unicode as backing store"); 303 return NULL; 304 305 } else { 306 Py_ssize_t size; 307 308 if (PyObject_AsWriteBuffer(py_data, &data, &size) == -1) { 309 return NULL; 310 } 311 } 312 313 314 CGContextRef ctx = NULL; 315 PyObjC_DURING 316 ctx = CGBitmapContextCreate(data, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo); 317 318 PyObjC_HANDLER 319 ctx = NULL; 320 PyObjCErr_FromObjC(localException); 321 PyObjC_ENDHANDLER 322 323 if (ctx == NULL && PyErr_Occurred()) { 324 return NULL; 325 } 326 327 if (ctx == NULL) { 328 Py_INCREF(Py_None); 329 return Py_None; 330 } 331 332 PyObject* rv = PyObjC_ObjCToPython(@encode(CGContextRef), &ctx); 333 CFRelease(ctx); 334 return rv; 335} 336 337 338static PyMethodDef m_methods[] = { 339#ifndef OS_TIGER 340 { 341 "CGFontCopyTableTags", 342 (PyCFunction)m_CGFontCopyTableTags, 343 METH_VARARGS, 344 NULL 345 }, 346 { 347 "CGWindowListCreate", 348 (PyCFunction)m_CGWindowListCreate, 349 METH_VARARGS, 350 NULL 351 }, 352 { 353 "CGWindowListCreateDescriptionFromArray", 354 (PyCFunction)m_CGWindowListCreateDescriptionFromArray, 355 METH_VARARGS, 356 NULL 357 }, 358 { 359 "CGWindowListCreateImageFromArray", 360 (PyCFunction)m_CGWindowListCreateImageFromArray, 361 METH_VARARGS, 362 NULL 363 }, 364#endif /* !OS_TIGER */ 365 { 366 "CGBitmapContextCreate", 367 (PyCFunction)m_CGBitmapContextCreate, 368 METH_VARARGS, 369 NULL 370 }, 371 372 373 { 0, 0, 0, } 374}; 375 376void init_coregraphics(void); 377void init_coregraphics(void) 378{ 379 PyObject* m = Py_InitModule4("_coregraphics", m_methods, 380 NULL, NULL, PYTHON_API_VERSION); 381 382 if (PyObjC_ImportAPI(m) < 0) { return; } 383} 384