Beispiel #1
0
/**
 * Return a pointer to the data of a writable buffer from obj. If only a
 * read-only buffer is available and force is True, a read-write buffer based on
 * the read-only buffer is obtained. Note that this may have some surprising
 * effects on buffers which expect the data from their read-only buffer not to
 * be modified.
 */
static PyObject*
memoryview_get_buffer(PyObject *self, PyObject *args){
    PyObject *obj = NULL;
    int force = 0;
    PyObject *ret = NULL;
    void * ptr = NULL;
    const void* roptr = NULL;
    Py_ssize_t buflen;
    Py_buffer buf;

    if (!PyArg_ParseTuple(args, "O|i", &obj, &force))
        return NULL;

    if (!get_buffer(obj, &buf, force)) { /* new buffer api */
        ret = PyLong_FromVoidPtr(buf.buf);
        free_buffer(&buf);
    } else { /* old buffer api */
        PyErr_Clear();
        if (-1 == PyObject_AsWriteBuffer(obj, &ptr, &buflen)) {
          if (!force)
            return NULL;
          PyErr_Clear();
          if(-1 == PyObject_AsReadBuffer(obj, &roptr, &buflen))
            return NULL;
          ptr = (void*) roptr;
        }
        ret = PyLong_FromVoidPtr(ptr);
    }
    return ret;
}
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
    Py_ssize_t buflen;

    buf->ptr = NULL;
    buf->flags = BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return PY_SUCCEED;
    }
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return PY_FAIL;
        }
    }
    buf->len = (intp) buflen;

    /* Point to the base of the buffer object if present */
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return PY_SUCCEED;
}
Beispiel #3
0
//-----------------------------------------------------------------------------
// cxBuffer_FromObject()
//   Populate the string buffer from a unicode object.
//-----------------------------------------------------------------------------
static int cxBuffer_FromObject(
    udt_Buffer *buf,                    // buffer to fill
    PyObject *obj,                      // object (string or Unicode object)
    const char *encoding)               // encoding to use, if applicable
{
    if (!obj)
        return cxBuffer_Init(buf);
    if (encoding && PyUnicode_Check(obj)) {
        buf->obj = PyUnicode_AsEncodedString(obj, encoding, NULL);
        if (!buf->obj)
            return -1;
        buf->ptr = PyBytes_AS_STRING(buf->obj);
        buf->size = PyBytes_GET_SIZE(buf->obj);
        buf->numCharacters = PyUnicode_GET_SIZE(obj);
    } else if (PyBytes_Check(obj)) {
        Py_INCREF(obj);
        buf->obj = obj;
        buf->ptr = PyBytes_AS_STRING(buf->obj);
        buf->size = buf->numCharacters = PyBytes_GET_SIZE(buf->obj);
#if PY_MAJOR_VERSION < 3
    } else if (PyBuffer_Check(obj)) {
        if (PyObject_AsReadBuffer(obj, &buf->ptr, &buf->size) < 0)
            return -1;
        Py_INCREF(obj);
        buf->obj = obj;
        buf->numCharacters = buf->size;
#endif
    } else {
        PyErr_SetString(PyExc_TypeError, CXORA_TYPE_ERROR);
        return -1;
    }
    return 0;
}
Beispiel #4
0
static py::object unpack( py::object bytes )
{
    auto p = bytes.ptr();

    if( !p )
    {
        throw std::runtime_error( "can't unpack: no object" );
    }

    const void * data = nullptr;
    Py_ssize_t size = 0;

    if( PyObject_AsReadBuffer( p, &data, &size ) )
    {
        py::throw_error_already_set();
    }

    if( !data || !size )
    {
        throw std::runtime_error( "can't unpack: no data" );
    }

    Unpacker unpacker( reinterpret_cast< char const * >( data ), size );

    return unpacker.unpack();
}
Beispiel #5
0
// Buffer conversion functions that use DWORD for length
BOOL PyWinObject_AsReadBuffer(PyObject *ob, void **buf, DWORD *buf_len, BOOL bNoneOk)
{
	if (ob==Py_None){
		if (bNoneOk){
			*buf_len=0;
			*buf=NULL;
			return TRUE;
			}
		PyErr_SetString(PyExc_TypeError, "Buffer cannot be None");
		return FALSE;
		}
	Py_ssize_t py_len;
	if (PyObject_AsReadBuffer(ob, (const void **)buf, &py_len)==-1)
		return FALSE;

#ifdef _WIN64
	if (py_len>MAXDWORD){
		PyErr_Format(PyExc_ValueError,"Buffer length can be at most %d characters", MAXDWORD);
		return FALSE;
		}
#endif

	*buf_len=(DWORD)py_len;
	return TRUE;
}
Beispiel #6
0
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
#if defined(NPY_PY3K)
    Py_buffer view;
#else
    Py_ssize_t buflen;
#endif

    buf->ptr = NULL;
    buf->flags = NPY_ARRAY_BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return NPY_SUCCEED;
    }

#if defined(NPY_PY3K)
    if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE) != 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_GetBuffer(obj, &view, PyBUF_ANY_CONTIGUOUS) != 0) {
            return NPY_FAIL;
        }
    }

    buf->ptr = view.buf;
    buf->len = (npy_intp) view.len;

    /*
     * XXX: PyObject_AsWriteBuffer does also this, but it is unsafe, as there is
     * no strict guarantee that the buffer sticks around after being released.
     */
    PyBuffer_Release(&view);

    /* Point to the base of the buffer object if present */
    if (PyMemoryView_Check(obj)) {
        buf->base = PyMemoryView_GET_BASE(obj);
    }
#else
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return NPY_FAIL;
        }
    }
    buf->len = (npy_intp) buflen;

    /* Point to the base of the buffer object if present */
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
#endif
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return NPY_SUCCEED;
}
Beispiel #7
0
NS_IMETHODIMP
PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval)
{
	NS_PRECONDITION(_retval, "null pointer");
	NS_PRECONDITION(buf, "null pointer");
	CEnterLeavePython _celp;
	PyObject *ret;
	const char *methodName = "read";
	nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
	if (NS_SUCCEEDED(nr)) {
#ifndef VBOX /* unsafe cast on 64-bit hosts. */
		PRUint32 py_size;
		const void *py_buf;
		if (PyObject_AsReadBuffer(ret, &py_buf, (Py_ssize_t*)&py_size)!=0) {
#else  /* VBOX */
		const void *py_buf;
# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
                Py_ssize_t py_size;
# else
                int py_size;
# endif /* VBOX */
		if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) {
#endif /* VBOX */
			PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", ret->ob_type->tp_name);
			nr = HandleNativeGatewayError(methodName);
		} else {
			if (py_size > count) {
				PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
				py_size = count;
			}
			memcpy(buf, py_buf, py_size);
			*_retval = py_size;
		}
	}
	return nr;
}


NS_IMETHODIMP
PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval)
{
	NS_WARNING("ReadSegments() not implemented!!!");
	return NS_ERROR_NOT_IMPLEMENTED;
}
PyObject *lightblueobex_filetostream(obex_t *obex, obex_object_t *obj, PyObject *fileobj, int bufsize)
{
    const void *data;
    Py_ssize_t datalen;        /* or unsigned int? */
    obex_headerdata_t hv;
    PyObject *buf;

    DEBUG("%s()\n", __func__);

    if (fileobj == NULL) {
        DEBUG("\tgiven file object is NULL\n");
        hv.bs = NULL;
        OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hv, 0,
                OBEX_FL_STREAM_DATAEND);
        return NULL;
    }

    buf = PyObject_CallMethod(fileobj, "read", "i", bufsize);
    if (buf == NULL) {
        if (PyErr_Occurred()) {
            PyErr_Print();
            PyErr_Clear();  /* let caller set exception */
        }
        DEBUG("\terror calling file object read()\n");
    }

    if (buf != NULL && !PyObject_CheckReadBuffer(buf)) {
        DEBUG("\tfile object read() returned non-buffer object\n");
        Py_DECREF(buf);
        buf = NULL;
    }

    if (buf != NULL && PyObject_AsReadBuffer(buf, &data, &datalen) < 0) {
        DEBUG("\terror reading file object contents\n");
        Py_DECREF(buf);
        buf = NULL;
    }

    if (buf == NULL) {
        hv.bs = NULL;
        OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hv, 0,
                OBEX_FL_STREAM_DATAEND);
        return NULL;
    }

    hv.bs = (uint8_t*)data;
    if (OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, hv, datalen,
           (datalen == 0 ? OBEX_FL_STREAM_DATAEND : OBEX_FL_STREAM_DATA)) < 0) {
        DEBUG("\terror adding body data\n");
        Py_DECREF(buf);
        buf = NULL;
    }

    return buf;
}
Beispiel #9
0
// this function creates a read buffer from PyObject which will be used
// for all write_<something> functions.
const void *
ImageOutputWrap::make_read_buffer (object &buffer, imagesize_t size)
{
    const void *buf = NULL; 
    Py_ssize_t len = 0;
    int success = PyObject_AsReadBuffer(buffer.ptr(), &buf, &len);
    if (success != 0 || imagesize_t(len) < size) {
        throw_error_already_set();
    }
    return buf;
}
Beispiel #10
0
int object_as_buffer(PyObject *obj, const void ** buffer, Py_ssize_t * buffer_len) {
    Py_buffer *rpybuf;
    if (PyMemoryView_Check(obj)) {
        rpybuf = PyMemoryView_GET_BUFFER(obj);
        if (rpybuf->buf==NULL)
        	return 1;
        buffer[0] = rpybuf->buf;
        return 0;
    }
    return PyObject_AsReadBuffer(obj, buffer, buffer_len);
}
Beispiel #11
0
Py::Object
_image_module::frombuffer(const Py::Tuple& args) {
  _VERBOSE("_image_module::frombuffer");

  args.verify_length(4);

  PyObject *bufin = new_reference_to(args[0]);
  int x = Py::Int(args[1]);
  int y = Py::Int(args[2]);
  int isoutput = Py::Int(args[3]);

  if (PyObject_CheckReadBuffer(bufin) != 1)
    throw Py::ValueError("First argument must be a buffer.");

  Image* imo = new Image;

  imo->rowsIn = y;
  imo->colsIn = x;
  Py_ssize_t NUMBYTES(imo->colsIn * imo->rowsIn * imo->BPP);

  Py_ssize_t buflen;
  const agg::int8u *rawbuf;
  if (PyObject_AsReadBuffer(bufin, reinterpret_cast<const void**>(&rawbuf), &buflen) != 0)
    throw Py::ValueError("Cannot get buffer from object.");

  // Check buffer is required size.
  if (buflen != NUMBYTES)
    throw Py::ValueError("Buffer length must be width * height * 4.");

  // Copy from input buffer to new buffer for agg.
  agg::int8u* buffer = new agg::int8u[NUMBYTES];
  if (buffer==NULL) //todo: also handle allocation throw
    throw Py::MemoryError("_image_module::frombuffer could not allocate memory");
  memmove(buffer, rawbuf, NUMBYTES);

  if (isoutput) {
    // make the output buffer point to the input buffer

    imo->rowsOut  = imo->rowsIn;
    imo->colsOut  = imo->colsIn;

    imo->rbufOut = new agg::rendering_buffer;
    imo->bufferOut = buffer;
    imo->rbufOut->attach(imo->bufferOut, imo->colsOut, imo->rowsOut, imo->colsOut * imo->BPP);

  }
  else {
    imo->bufferIn = buffer;
    imo->rbufIn = new agg::rendering_buffer;
    imo->rbufIn->attach(buffer, imo->colsIn, imo->rowsIn, imo->colsIn*imo->BPP);
  }

  return Py::asObject(imo);
}
Beispiel #12
0
static PyObject *
xpybExt_send_request(xpybExt *self, PyObject *args, PyObject *kw)
{
    static char *kwlist[] = { "request", "cookie", "reply", NULL };
    xpybRequest *request;
    xpybCookie *cookie;
    PyTypeObject *reply = NULL;
    xcb_protocol_request_t xcb_req;
    struct iovec xcb_parts[4];
    unsigned int seq;
    int flags;
    const void *data;
    Py_ssize_t size;

    /* Parse and check arguments */
    if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O!", kwlist,
				     &xpybRequest_type, &request,
				     &xpybCookie_type, &cookie,
				     &PyType_Type, &reply))
	return NULL;

    if (!request->is_void)
	if (reply == NULL || !PyType_IsSubtype(reply, &xpybReply_type)) {
	    PyErr_SetString(xpybExcept_base, "Reply type missing or not derived from xcb.Reply.");
	    return NULL;
	}

    /* Set up request structure */
    xcb_req.count = 2;
    xcb_req.ext = (self->key != (xpybExtkey *)Py_None) ? &self->key->key : 0;
    xcb_req.opcode = request->opcode;
    xcb_req.isvoid = request->is_void;

    /* Allocate and fill in data strings */
    if (PyObject_AsReadBuffer(((xpybProtobj *)request)->buf, &data, &size) < 0)
	return NULL;
    xcb_parts[2].iov_base = (void *)data;
    xcb_parts[2].iov_len = size;
    xcb_parts[3].iov_base = 0;
    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;

    /* Make request call */
    flags = request->is_checked ? XCB_REQUEST_CHECKED : 0;
    seq = xcb_send_request(self->conn->conn, flags, xcb_parts + 2, &xcb_req);

    /* Set up cookie */
    Py_INCREF(cookie->conn = self->conn);
    Py_INCREF((PyObject *)(cookie->request = request));
    Py_XINCREF(cookie->reply = reply);
    cookie->cookie.sequence = seq;

    Py_INCREF(cookie);
    return (PyObject *)cookie;
}
static int lightblueobex_addbytestreamheader(obex_t *obex, obex_object_t *obj, uint8_t hi, PyObject *bufObject)
{
    obex_headerdata_t hv;
    uint32_t hv_size;

    DEBUG("%s()\n", __func__);

    if (PyObject_AsReadBuffer(bufObject, (const void**)&hv.bs, (Py_ssize_t*)&hv_size) < 0) {
        DEBUG("\theader value for id 0x%02x must be readable buffer\n", hi);
        return -1;
    }
    return OBEX_ObjectAddHeader(obex, obj, hi, hv, hv_size, OBEX_FL_FIT_ONE_PACKET);
}
Beispiel #14
0
static PyObject *
xpybResponse_getattro(PyObject *self, PyObject *obj)
{
    const char *name = PyString_AS_STRING(obj);
    const xcb_generic_event_t *data;
    Py_ssize_t size;

    if (PyObject_AsReadBuffer(self, (const void **)&data, &size) < 0)
	return NULL;

    if (strcmp(name, "response_type") == 0)
	return Py_BuildValue("B", data->response_type);
    if (strcmp(name, "sequence") == 0)
	return Py_BuildValue("H", data->sequence);

    return xpybResponse_type.tp_base->tp_getattro(self, obj);
}
Beispiel #15
0
	static PyObject* buffer_set( PyIOCPBufferObject* s, PyObject *args )
	{
		const void * buffer_ptr = 0 ;
		DWORD buffer_len = 0;
		DWORD buffer_set_length = -1;
		PyObject* o = 0;
		int r = PyArg_ParseTuple( args, "O|I", &o, &buffer_set_length );
		if( r == 0 ) return param_error( );
		r = PyObject_AsReadBuffer( o, &buffer_ptr, (Py_ssize_t *) &buffer_len );
		if( r != 0 ) return param_error( );
		if( buffer_set_length < buffer_len )
			buffer_len = buffer_set_length;
		DWORD mov_num = buffer_len;
		if( s->len < mov_num ) mov_num = s->len ;
		memcpy_s( s->ptr_start, s->len, buffer_ptr, mov_num );
		Py_RETURN_NONE;
	}
// Utf8Validator - validate
static PyObject* Utf8Validator_validate(Utf8Validator *self, PyObject *args)
{
    /* Declarations */
    int valid;
    int state;
    int i;
    uint8_t *buf;
    Py_ssize_t buf_len;
    PyObject *py_buf;
    
    /* Parse input arguments */
    if (!PyArg_ParseTuple(args, "O:validate", &py_buf))
        return NULL;
    
    if (PyObject_AsReadBuffer(py_buf, (const void**) &buf, &buf_len))
        return NULL;
    
    /* Initialize local variables */
    valid = 1;
    state = self->state;
    
    /* Validate bytes */
    for (i = 0; i < (int) buf_len; ++i)
    {
        state = UTF8VALIDATOR_DFA[256 + (state << 4) + UTF8VALIDATOR_DFA[buf[i]]];
        
        if (state == UTF8_REJECT)
        {
            valid = 0;
            break;
        }
    }
    
    /* Store results of validation */
    self->i += i;
    self->state = state;
    
    /* Return the results */
    return Py_BuildValue("OOii",
                         valid ? Py_True : Py_False,
                         state == UTF8_ACCEPT ? Py_True : Py_False,
                         i,
                         self->i);
}
Beispiel #17
0
static PyObject*
_sdl_wmseticon (PyObject *self, PyObject *args)
{
    PyObject *surface;
    PyObject *mask = NULL;
    Uint8 *maskbuf = NULL;
    Py_ssize_t masklen = 0;
    SDL_Surface *sdlsurface;

    ASSERT_VIDEO_INIT(NULL);

    if (SDL_GetVideoSurface ())
    {
        PyErr_SetString (PyExc_PyGameError, "video surface already exists");
        return NULL;
    }

    if (!PyArg_ParseTuple (args, "O|O:set_icon", &surface, &mask))
        return NULL;

    if (!PySDLSurface_Check (surface))
    {
        PyErr_SetString (PyExc_TypeError, "surface must be a Surface");
        return NULL;
    }
    sdlsurface = PySDLSurface_AsSDLSurface (surface);
    
    if (mask)
    {
        int w;
        if (PyObject_AsReadBuffer (mask, (const void**)&maskbuf,
            &masklen) == -1)
            return NULL;
        w = (int) round ((masklen * 1.f) / sdlsurface->h);
        if ((w * 8) != sdlsurface->w)
        {
            PyErr_SetString (PyExc_ValueError,
                "mask buffer does not match size");
            return NULL;
        }
    }
    SDL_WM_SetIcon (((PySDLSurface*)surface)->surface, maskbuf);
    Py_RETURN_NONE;
}
static PyObject *image_frombuffer(PyObject *self, PyObject *args, PyObject *kwds)
{
    PyObject *buffer;
    unsigned x;
    unsigned y;
    int isoutput;
    const char *names[] = { "buffer", "x", "y", "isoutput", NULL };

    if (!PyArg_ParseTupleAndKeywords(
             args, kwds, "OII|i:frombuffer", (char **)names, &buffer, &x, &y, &isoutput)) {
        return NULL;
    }

    const void *rawbuf;
    Py_ssize_t buflen;
    if (PyObject_AsReadBuffer(buffer, &rawbuf, &buflen) != 0) {
        return NULL;
    }

    if (buflen != (Py_ssize_t)(y * x * 4)) {
        PyErr_SetString(PyExc_ValueError, "Buffer is incorrect length");
        return NULL;
    }

    Image *im;
    CALL_CPP("frombuffer", (im = new Image(y, x, isoutput)));

    agg::int8u *inbuf = (agg::int8u *)rawbuf;
    agg::int8u *outbuf;
    if (isoutput) {
        outbuf = im->bufferOut;
    } else {
        outbuf = im->bufferIn;
    }

    for (int i = (x * 4) * (y - 1); i >= 0; i -= (x * 4)) {
        memmove(outbuf, &inbuf[i], (x * 4));
        outbuf += x * 4;
    }

    return PyImage_cnew(im);
}
Beispiel #19
0
void pyVaultImageNode::SetImageFromBuf( PyObject * pybuf )
{
    if (!fNode)
        return;

    if (fMipmapKey) {
        fMipmapKey->UnRefObject();
        fMipmapKey = nil;
        fMipmap = nil;
    }

    uint8_t * buffer = nil;
    Py_ssize_t bytes;
    PyObject_AsReadBuffer(pybuf, (const void **)&buffer, &bytes);
    if (buffer) {
        VaultImageNode access(fNode);
        access.SetImageData(buffer, bytes);
        access.SetImageType(VaultImageNode::kJPEG);
    }
}
Beispiel #20
0
static PyObject *
newIobject(PyObject *s) {
  Iobject *self;
  char *buf;
  Py_ssize_t size;

  if (PyObject_AsReadBuffer(s, (const void **)&buf, &size)) {
      PyErr_Format(PyExc_TypeError, "expected read buffer, %.200s found",
		   s->ob_type->tp_name);
      return NULL;
  }
  self = PyObject_New(Iobject, &Itype);
  if (!self) return NULL;
  Py_INCREF(s);
  self->buf=buf;
  self->string_size=size;
  self->pbuf=s;
  self->pos=0;
  
  return (PyObject*)self;
}
Beispiel #21
0
static PyObject*
memoryview_get_extents(PyObject *self, PyObject *args)
{
    PyObject *obj = NULL;
    PyObject *ret = NULL;
    Py_buffer b;
    const void * ptr = NULL;
    Py_ssize_t bufptr, buflen;
    if (!PyArg_ParseTuple(args, "O", &obj))
        return NULL;

    if (!get_buffer(obj, &b, 0)) { /* new buffer api */
        ret = get_extents(b.shape, b.strides, b.ndim, b.itemsize,
                          (Py_ssize_t)b.buf);
        free_buffer(&b);
    } else { /* old buffer api */
        PyErr_Clear();
        if (-1 == PyObject_AsReadBuffer(obj, &ptr, &buflen)) return NULL;
        bufptr = (Py_ssize_t)ptr;
        ret = Py_BuildValue("nn", bufptr, bufptr + buflen);
    }
    return ret;
}
Beispiel #22
0
/*NUMPY_API
 * Get buffer chunk from object
 *
 * this function takes a Python object which exposes the (single-segment)
 * buffer interface and returns a pointer to the data segment
 *
 * You should increment the reference count by one of buf->base
 * if you will hang on to a reference
 *
 * You only get a borrowed reference to the object. Do not free the
 * memory...
 */
NPY_NO_EXPORT int
PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
{
    Py_ssize_t buflen;

    buf->ptr = NULL;
    buf->flags = NPY_ARRAY_BEHAVED;
    buf->base = NULL;
    if (obj == Py_None) {
        return NPY_SUCCEED;
    }
    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
        PyErr_Clear();
        buf->flags &= ~NPY_ARRAY_WRITEABLE;
        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
                                  &buflen) < 0) {
            return NPY_FAIL;
        }
    }
    buf->len = (npy_intp) buflen;

    /* Point to the base of the buffer object if present */
#if defined(NPY_PY3K)
    if (PyMemoryView_Check(obj)) {
        buf->base = PyMemoryView_GET_BASE(obj);
    }
#else
    if (PyBuffer_Check(obj)) {
        buf->base = ((PyArray_Chunk *)obj)->base;
    }
#endif
    if (buf->base == NULL) {
        buf->base = obj;
    }
    return NPY_SUCCEED;
}
Beispiel #23
0
static PyObject *
binary_quote(binaryObject *self)
{
    char *to = NULL;
    const char *buffer = NULL;
    Py_ssize_t buffer_len;
    size_t len = 0;
    PyObject *rv = NULL;
#if HAS_MEMORYVIEW
    Py_buffer view;
    int got_view = 0;
#endif

    /* if we got a plain string or a buffer we escape it and save the buffer */

#if HAS_MEMORYVIEW
    if (PyObject_CheckBuffer(self->wrapped)) {
        if (0 > PyObject_GetBuffer(self->wrapped, &view, PyBUF_CONTIG_RO)) {
            goto exit;
        }
        got_view = 1;
        buffer = (const char *)(view.buf);
        buffer_len = view.len;
    }
#endif

#if HAS_BUFFER
    if (!buffer && (Bytes_Check(self->wrapped) || PyBuffer_Check(self->wrapped))) {
        if (PyObject_AsReadBuffer(self->wrapped, (const void **)&buffer,
                                  &buffer_len) < 0) {
            goto exit;
        }
    }
#endif

    if (!buffer) {
        goto exit;
    }

    /* escape and build quoted buffer */

    to = (char *)binary_escape((unsigned char*)buffer, (size_t) buffer_len,
        &len, self->conn ? ((connectionObject*)self->conn)->pgconn : NULL);
    if (to == NULL) {
        PyErr_NoMemory();
        goto exit;
    }

    if (len > 0)
        rv = Bytes_FromFormat(
            (self->conn && ((connectionObject*)self->conn)->equote)
                ? "E'%s'::bytea" : "'%s'::bytea" , to);
    else
        rv = Bytes_FromString("''::bytea");

exit:
    if (to) { PQfreemem(to); }
#if HAS_MEMORYVIEW
    if (got_view) { PyBuffer_Release(&view); }
#endif

    /* Allow Binary(None) to work */
    if (self->wrapped == Py_None) {
        Py_INCREF(psyco_null);
        rv = psyco_null;
    }

    /* if the wrapped object is not bytes or a buffer, this is an error */
    if (!rv && !PyErr_Occurred()) {
        PyErr_Format(PyExc_TypeError, "can't escape %s to binary",
            Py_TYPE(self->wrapped)->tp_name);
    }

    return rv;
}
Beispiel #24
0
/* This is a hacked version of Python's fileobject.c:file_writelines(). */
static PyObject *
fcgi_Stream_writelines(fcgi_Stream *self, PyObject *seq)
{
#define CHUNKSIZE 1000
    FCGX_Stream *s;
    PyObject *list, *line;
    PyObject *it;   /* iter(seq) */
    PyObject *result;
    int i, j, index, len, nwritten, islist;

    fcgi_Stream_Check();

    s = *(self->s);

    result = NULL;
    list = NULL;
    islist = PyList_Check(seq);
    if  (islist)
        it = NULL;
    else {
        it = PyObject_GetIter(seq);
        if (it == NULL) {
            PyErr_SetString(PyExc_TypeError,
                "writelines() requires an iterable argument");
            return NULL;
        }
        /* From here on, fail by going to error, to reclaim "it". */
        list = PyList_New(CHUNKSIZE);
        if (list == NULL)
            goto error;
    }

    /* Strategy: slurp CHUNKSIZE lines into a private list,
       checking that they are all strings, then write that list
       without holding the interpreter lock, then come back for more. */
    for (index = 0; ; index += CHUNKSIZE) {
        if (islist) {
            Py_XDECREF(list);
            list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
            if (list == NULL)
                goto error;
            j = PyList_GET_SIZE(list);
        }
        else {
            for (j = 0; j < CHUNKSIZE; j++) {
                line = PyIter_Next(it);
                if (line == NULL) {
                    if (PyErr_Occurred())
                        goto error;
                    break;
                }
                PyList_SetItem(list, j, line);
            }
        }
        if (j == 0)
            break;

        /* Check that all entries are indeed strings. If not,
           apply the same rules as for file.write() and
           convert the results to strings. This is slow, but
           seems to be the only way since all conversion APIs
           could potentially execute Python code. */
        for (i = 0; i < j; i++) {
            PyObject *v = PyList_GET_ITEM(list, i);
            if (!PyString_Check(v)) {
                    const char *buffer;
                    int len;
                if (PyObject_AsReadBuffer(v,
                          (const void**)&buffer,
                                &len) ||
                     PyObject_AsCharBuffer(v,
                               &buffer,
                               &len)) {
                    PyErr_SetString(PyExc_TypeError,
            "writelines() argument must be a sequence of strings");
                    goto error;
                }
                line = PyString_FromStringAndSize(buffer,
                                  len);
                if (line == NULL)
                    goto error;
                Py_DECREF(v);
                PyList_SET_ITEM(list, i, line);
            }
        }

        /* Since we are releasing the global lock, the
           following code may *not* execute Python code. */
        Py_BEGIN_ALLOW_THREADS
        errno = 0;
        for (i = 0; i < j; i++) {
                line = PyList_GET_ITEM(list, i);
            len = PyString_GET_SIZE(line);
            nwritten = FCGX_PutStr(PyString_AS_STRING(line), len, s);
            if (nwritten != len) {
                Py_BLOCK_THREADS
                if (nwritten < 0) {
                    PyErr_SetString(PyExc_IOError, "Write failed");
                } else {
                    char msgbuf[256];
                    PyOS_snprintf(msgbuf, sizeof(msgbuf),
                          "Write failed, wrote %d of %d bytes",
                          nwritten, len);
                    PyErr_SetString(PyExc_IOError, msgbuf);
                }
                goto error;
            }
        }
        Py_END_ALLOW_THREADS

        if (j < CHUNKSIZE)
            break;
    }
Beispiel #25
0
// this code is heavily adapted from the paint license, which is in
// the file paint.license (BSD compatible) included in this
// distribution.  TODO, add license file to MANIFEST.in and CVS
Py::Object _png_module::write_png(const Py::Tuple& args)
{
    args.verify_length(4, 5);

    FILE *fp = NULL;
    bool close_file = false;
    bool close_dup_file = false;
    Py::Object buffer_obj = Py::Object(args[0]);
    PyObject* buffer = buffer_obj.ptr();
    if (!PyObject_CheckReadBuffer(buffer))
    {
        throw Py::TypeError("First argument must be an rgba buffer.");
    }

    const void* pixBufferPtr = NULL;
    Py_ssize_t pixBufferLength = 0;
    if (PyObject_AsReadBuffer(buffer, &pixBufferPtr, &pixBufferLength))
    {
        throw Py::ValueError("Couldn't get data from read buffer.");
    }

    png_byte* pixBuffer = (png_byte*)pixBufferPtr;
    int width = (int)Py::Int(args[1]);
    int height = (int)Py::Int(args[2]);

    if (pixBufferLength < width * height * 4)
    {
        throw Py::ValueError("Buffer and width, height don't seem to match.");
    }

    Py::Object py_fileobj = Py::Object(args[3]);
    PyObject* py_file = NULL;
    if (py_fileobj.isString())
    {
        if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"wb")) == NULL) {
            throw Py::Exception();
        }
        close_file = true;
    }
    else
    {
        py_file = py_fileobj.ptr();
    }

    if ((fp = npy_PyFile_Dup(py_file, (char *)"wb")))
    {
        close_dup_file = true;
    }
    else
    {
        PyErr_Clear();
        PyObject* write_method = PyObject_GetAttrString(
                py_file, "write");
        if (!(write_method && PyCallable_Check(write_method)))
        {
            Py_XDECREF(write_method);
            throw Py::TypeError(
                    "Object does not appear to be a 8-bit string path or "
                    "a Python file-like object");
        }
        Py_XDECREF(write_method);
    }

    png_bytep *row_pointers = NULL;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    try
    {
        struct png_color_8_struct sig_bit;
        png_uint_32 row;

        row_pointers = new png_bytep[height];
        for (row = 0; row < (png_uint_32)height; ++row)
        {
            row_pointers[row] = pixBuffer + row * width * 4;
        }

        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if (png_ptr == NULL)
        {
            throw Py::RuntimeError("Could not create write struct");
        }

        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
            throw Py::RuntimeError("Could not create info struct");
        }

        if (setjmp(png_jmpbuf(png_ptr)))
        {
            throw Py::RuntimeError("Error building image");
        }

        if (fp)
        {
            png_init_io(png_ptr, fp);
        }
        else
        {
            png_set_write_fn(png_ptr, (void*)py_file,
                             &write_png_data, &flush_png_data);
        }
        png_set_IHDR(png_ptr, info_ptr,
                     width, height, 8,
                     PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
                     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

        // Save the dpi of the image in the file
        if (args.size() == 5)
        {
            double dpi = Py::Float(args[4]);
            size_t dots_per_meter = (size_t)(dpi / (2.54 / 100.0));
            png_set_pHYs(png_ptr, info_ptr, dots_per_meter, dots_per_meter, PNG_RESOLUTION_METER);
        }

        // this a a color image!
        sig_bit.gray = 0;
        sig_bit.red = 8;
        sig_bit.green = 8;
        sig_bit.blue = 8;
        /* if the image has an alpha channel then */
        sig_bit.alpha = 8;
        png_set_sBIT(png_ptr, info_ptr, &sig_bit);

        png_write_info(png_ptr, info_ptr);
        png_write_image(png_ptr, row_pointers);
        png_write_end(png_ptr, info_ptr);
    }
    catch (...)
    {
        if (png_ptr && info_ptr)
        {
            png_destroy_write_struct(&png_ptr, &info_ptr);
        }
        delete [] row_pointers;

        if (close_dup_file)
        {
            if (npy_PyFile_DupClose(py_file, fp)) {
              throw Py::RuntimeError("Error closing dupe file handle");
            }
        }

        if (close_file)
        {
            npy_PyFile_CloseFile(py_file);
            Py_DECREF(py_file);
        }
        /* Changed calls to png_destroy_write_struct to follow
           http://www.libpng.org/pub/png/libpng-manual.txt.
           This ensures the info_ptr memory is released.
        */
        throw;
    }

    png_destroy_write_struct(&png_ptr, &info_ptr);
    delete [] row_pointers;
    if (close_dup_file)
    {
        if (npy_PyFile_DupClose(py_file, fp)) {
          throw Py::RuntimeError("Error closing dupe file handle");
        }
    }

    if (close_file)
    {
        npy_PyFile_CloseFile(py_file);
        Py_DECREF(py_file);
    }

    if (PyErr_Occurred()) {
        throw Py::Exception();
    } else {
        return Py::Object();
    }
}
PyObject *TileEngine::getTileData(
    PyObject *tileFunction,
    PyObject *tileMap,
    int col,
    int row,
    int cols,
    int rows,
    int code,
    PyObject *tileViewCache)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	Py_INCREF(Py_None);
	return Py_None;
    }

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

        if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    Py_INCREF(Py_None);
	    return Py_None;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    Py_INCREF(Py_None);
	    return Py_None;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap read buffer of 4 byte integers");
	    Py_INCREF(Py_None);
	    return Py_None;
	}
    }

    int *tileViewCacheData = NULL;
    int tileViewCacheCount = 0;

    if (tileViewCache != Py_None) {
	tileViewCacheCount =
	    (unsigned int)PySequence_Size(tileViewCache);
	Py_ssize_t tileViewCacheLength = 0;
	if ((tileViewCacheCount != (width * height)) ||
	    (PyObject_AsWriteBuffer(
	       tileViewCache,
	       (void **)&tileViewCacheData,
	       &tileViewCacheLength) != 0)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileViewCache with write buffer");
	    Py_INCREF(Py_None);
	    return Py_None;
	}
    }

    const char *textCodeString =
	"0123456789"
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ+-";
    int tileSize = sizeof(unsigned short);
    int r, c;
    int bufSize = 0;
    char *buf = NULL;
    bool returnBuffer = false;

    switch (code) {

	case TILE_CODE_RAW_BINARY_16: {
	    bufSize = tileSize * rows * cols;
	    buf = (char *)malloc(bufSize);
	    unsigned char *dst = (unsigned char *)buf;

	    for (r = 0; r < rows; r++) {
		for (c = 0; c < cols; c++) {
		    int tile = 
			getValue(
			    col + c, 
			    row + r, 
			    tileFunction, 
			    tileMapData, 
			    tileMapCount);
		    *dst++ = (tile >> 8) & 0xff; // High byte.
		    *dst++ = tile & 0xff; // Low byte.
		}
	    }
	    break;
	}

	case TILE_CODE_COMPRESSED_TEXT: {
	    bufSize = tileSize * rows * cols * 3; // to be safe
	    buf = (char *)malloc(bufSize);
	    unsigned char *dst = (unsigned char *)buf;
	    int tileIndex = 0;
	    int tileIndexMax = rows * cols;
	    int offset = 0;
	    int skip = 0;

	    while ((tileIndex < tileIndexMax) &&
		   (offset < bufSize)) {
		int c = tileIndex % cols;
		int r = tileIndex / cols;
		int tileCacheOffset = 
		    (col + c) + ((row + r) * width);
//		printf("tileIndex %d tileCacheOffset %d tileViewCacheCount %d c %d r %d cols %d rows %d ",
//		    tileIndex,
//		    tileCacheOffset,
//		    tileViewCacheCount,
//		    c, r, cols, rows);
		int tile = 
		    getValue(
			col + c, 
			row + r, 
			tileFunction,
			tileMapData, 
			tileMapCount);
//		printf("tile %d\n", tile);
		int curTile =
		    (tileViewCacheData == NULL)
			? -1
			: tileViewCacheData[tileCacheOffset];

		if (tile == curTile) {
		    skip++;
		} else {
//		    printf("tile %d skip %d offset %d r %d c %d index %d\n", tile, skip, offset, r, c, c + (r * width));
		    if (skip) {
			if (skip == 1) {
//			    printf("skip 1\n");
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    offset++;
			} else if (skip == 2) {
//			    printf("skip 2/1\n");
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_0;
			    offset += 2;
			} else if (skip < 64) {
//			    printf("skip %d/64\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_1;
			    *dst++ = textCodeString[val];
			    offset += 2;
			} else if (skip < 4096) {
//			    printf("skip %d/4096\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_2;
			    *dst++ = textCodeString[(val >> 6) & 63]; // High.
			    *dst++ = textCodeString[val & 63]; // Low.
			    offset += 3;
			} else {
//			    printf("skip %d/999999\n", skip);
			    int val = skip;
			    *dst++ = TILE_CODE_COMPRESSED_TEXT_SKIP_3;
			    *dst++ = textCodeString[(val >> 12) & 63]; // Highest.
			    *dst++ = textCodeString[(val >> 6) & 63]; // High.
			    *dst++ = textCodeString[val & 63]; // Low.
			    offset += 4;
			}

			skip = 0;

		    }

		    if (tileViewCacheData != NULL) {
			tileViewCacheData[tileCacheOffset] = tile;
		    }

		    int low = tile & 63;
		    int high = (tile >> 6) & 63;
		    *dst++ = textCodeString[low];
		    *dst++ = textCodeString[high];

		    offset += 2;
		}

		tileIndex++;
	    }

	    bufSize = offset;

	    break;
	}
void TileEngine::renderPixels(
    cairo_surface_t *destSurf,
    cairo_surface_t *cmapSurf,
    PyObject *tileFunction,
    PyObject *tileMap,
    int renderCol,
    int renderRow,
    int renderCols,
    int renderRows)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	return;
    }

    // The tileMap should be None, or an array of 4 byte integers,
    // mapping virtual tiles indices to absolute tile numbers.

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

        if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    return;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    return;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	  PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileMap read buffer of 4 byte integers");
	  return;
	}
    }

    unsigned char *destData = cairo_image_surface_get_data(destSurf);
    int destStride = cairo_image_surface_get_stride(destSurf);

    unsigned char *cmapData = cairo_image_surface_get_data(cmapSurf);
    int cmapWidth = cairo_image_surface_get_width(cmapSurf);
    int cmapStride = cairo_image_surface_get_stride(cmapSurf);

    int r;
    for (r = 0; r < renderRows; r++) {
	int c;
	for (c = 0; c  < renderCols; c++) {
	    int col = (renderCol + c) % width;
	    int row = (renderRow + r) % height;

	    unsigned long tile = 
		getValue(
		    col,
		    row,
		    tileFunction,
		    tileMapData,
		    tileMapCount);

	    int sourceX = tile % cmapWidth;
	    int sourceY = tile / cmapWidth;

	    unsigned char *sourcePixel =
		cmapData +
		(sourceX * 4) +
		(sourceY * cmapStride);

	    unsigned char *destPixel =
		destData +
		(c * 4) +
		(r * destStride);

	    *(long *)destPixel = *(long *)sourcePixel;
	}
    }
}
void TileEngine::renderTilesLazy(
    cairo_t *ctx,
    PyObject *tileFunction,
    PyObject *tileMap,
    int tileSize,
    int renderCol,
    int renderRow,
    int renderCols,
    int renderRows,
    double alpha,
    PyObject *tileGenerator,
    PyObject *tileCache,
    PyObject *tileCacheSurfaces,
    PyObject *tileState)
{
    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	return;
    }

    // The tileMap should be None, or an array of 4 byte integers,
    // mapping virtual tiles indices to absolute tile numbers.

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {

      if (!PySequence_Check(tileMap)) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap to be an array "
		"of 4 byte integers or None");
	    return;
	}

	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    return;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap read buffer of 4 byte integers");
	    return;
	}
    }

    // The tileGenerator should be a function that takes one integer
    // tile parameter, and returns a tuple of three integers: a
    // surface index, a tileX and a tileY position.
    if (!PyCallable_Check(tileGenerator)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileGenerator callable object");
	return;
    }

    // The tileCache should be an array of integers, 4 integers per
    // tile.  The first is a "cached" flag, the second is a surface
    // index, the 3rd and 4th are a tileX and tileY position.

    int *tileCacheData = NULL;
    Py_ssize_t tileCacheLength = 0;

    if (PyObject_AsWriteBuffer(
	tileCache,
	(void **)&tileCacheData,
	&tileCacheLength) != 0) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileCache array");
	return;
    }

    // The tileCacheSurfaces parameters should be a list of Cairo
    // surfaces.
    if (!PySequence_Check(tileCacheSurfaces)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileCacheSurfaces sequence");
	return;
    }

    // The tileState parameters should be None or a list of tile state
    // parameters.
    if ((tileState != Py_None) &&
	!PySequence_Check(tileState)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileState sequence or None");
	return;
    }

    int renderX = renderCol * tileSize;
    int renderY = renderRow * tileSize;

    int r;
    for (r = 0; r < renderRows; r++) {
	int c;
	for (c = 0; c  < renderCols; c++) {
	    int col = (renderCol + c) % width;
	    int row = (renderRow + r) % height;

	    unsigned long tile = 
		getValue(
		    col,
		    row,
		    tileFunction,
		    tileMapData,
		    tileMapCount);

	    double x = col * tileSize;
	    double y = row * tileSize;

	    // Get the tile surface index, tileX and tileY from the
	    // cache, or call the tileGenerator function to produce
	    // them, if they are not already cached.

	    int cacheOffset = tile * 4;
	    int tileSurfaceIndex = 0;
	    int tileX = 0;
	    int tileY = 0;

	    if (tileCacheData[cacheOffset + 0]) {

		// The tile is already cached. 
		// Get the values from the tileCache. 

		tileSurfaceIndex = tileCacheData[cacheOffset + 1];
		tileX = tileCacheData[cacheOffset + 2];
		tileY = tileCacheData[cacheOffset + 3];

	    } else {

		// The tile has not already been cached.  Call the
		// tileGenerator function to produce the tile, passing
		// it the absolute tile number as a parameter.

		// Mark the tile as cached, so we don't do this again. 
		tileCacheData[cacheOffset + 0] = 1;

		PyObject *result =
		    PyObject_CallFunction(
			tileGenerator,
			"i",
			tile);

		// The tile function returns a tuple of three numbers:
		// the surface index (into the tileCacheSurfaces array
		// of Cairo surfaces), the tileX and tileY position in
		// the surface.

		if (result == NULL) {
		    PyErr_SetString(
			PyExc_TypeError,
			"tile generator did not return a result");
		    return;
		}

		int success =
		    PyArg_ParseTuple(
			result,
			"iii",
			&tileSurfaceIndex,
			&tileX,
			&tileY);
		Py_DECREF(result);
		if (!success) {
		    PyErr_SetString(
			PyExc_TypeError,
			"tile generator return wrong number of "
		        "results in tuple");
		    return;
		}

		// Cache the returned values. 
		tileCacheData[cacheOffset + 1] = tileSurfaceIndex;
		tileCacheData[cacheOffset + 2] = tileX;
		tileCacheData[cacheOffset + 3] = tileY;
	    }

	    // Get the Python object wrapping the Cairo surface for
	    // the tile.
	    PyObject *tiles =
		PySequence_GetItem(
		    tileCacheSurfaces,
		    tileSurfaceIndex);

	    if (tiles == NULL) {
		PyErr_SetString(
		    PyExc_TypeError,
		    "tile generator returned invalid tile "
		    "surface index");
		return;
	    }

	    if (!PyObject_TypeCheck(
		  tiles,
		  &PycairoSurface_Type)) {
		PyErr_SetString(
		    PyExc_TypeError,
		    "expected cairo_surface_t objects "
		    "in tileCacheSurfaces");
		return;
	    }

	    // Get the cairo_surface_t from the Python object.
	    cairo_surface_t *tilesSurf = PycairoSurface_GET(tiles);
	    Py_DECREF(tiles);

	    // Draw a tile.

	    cairo_save(ctx);

	    cairo_translate(
		ctx,
		x - renderX,
		y - renderY);

	    cairo_rectangle(
		ctx,
		0,
		0,
		tileSize,
		tileSize);

	    cairo_clip(ctx);

	    cairo_set_source_surface(
		ctx,
		tilesSurf,
		-tileX,
		-tileY);

	    if (alpha >= 1.0) {
		cairo_paint(ctx);
	    } else {
		cairo_paint_with_alpha(ctx, alpha);
	    }

	    cairo_restore(ctx);
	}
    }
}
// Render fixed sized tiles, pre-drawn into the Cairo surface "tiles".
void TileEngine::renderTiles(
    cairo_t *ctx,
    cairo_surface_t *tilesSurf,
    int tilesWidth,
    int tilesHeight,
    PyObject *tileFunction,
    PyObject *tileMap,
    int tileSize,
    int renderCol,
    int renderRow,
    int renderCols,
    int renderRows,
    double alpha)
{

    if ((tileFunction != Py_None) &&
	!PyCallable_Check(tileFunction)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileFunction to be a callable function or None");
	return;
    }

    // The tileMap should be an array of 4 byte integers,
    // mapping virtual tiles indices to absolute tile numbers.
    if ((tileMap != Py_None) &&
	!PySequence_Check(tileMap)) {
	PyErr_SetString(
	    PyExc_TypeError,
	    "expected tileMap to be an array "
	    "of 4 byte integers or None");
	return;
    }

    const int *tileMapData = NULL;
    unsigned int tileMapCount = 0;

    if (tileMap != Py_None) {
	tileMapCount = (unsigned int)PySequence_Size(tileMap);
	Py_ssize_t tileMapLength = 0;
	if (PyObject_AsReadBuffer(
	    tileMap,
	    (const void **)&tileMapData,
	    &tileMapLength) != 0) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap with read buffer");
	    return;
	}

	int tileMapDataCount = 
	    (int)tileMapLength / sizeof(unsigned int);

	if (tileMapDataCount != (int)tileMapCount) {
	    PyErr_SetString(
		PyExc_TypeError,
		"expected tileMap read buffer of 4 byte integers");
	    return;
	}
    }

    int tilesPerRow = tilesWidth / tileSize;

    int renderX = renderCol * tileSize;
    int renderY = renderRow * tileSize;

    int r;
    for (r = 0; r < renderRows; r++) {
	int c;
	for (c = 0; c  < renderCols; c++) {
	    int col = (renderCol + c) % width;
	    int row = (renderRow + r) % height;

	    unsigned long tile =
		getValue(
		    col,
		    row,
		    tileFunction,
		    tileMapData,
		    tileMapCount);

	    double x = col * tileSize;
	    double y = row * tileSize;

	    // Tiles are arranged in a regular grid. 
	    // Calculate the position of the file in the 
	    // source tileSurf. 
	    int tileCol = tile % tilesPerRow;
	    int tileRow = tile / tilesPerRow;
	    int tileX = tileCol * tileSize;
	    int tileY = tileRow * tileSize;

	    // Draw a tile.

	    cairo_save(ctx);

	    cairo_translate(
		ctx,
		x - renderX,
		y - renderY);

	    cairo_rectangle(
		ctx,
		0,
		0,
		tileSize,
		tileSize);

	    cairo_clip(ctx);

	    cairo_set_source_surface(
		ctx,
		tilesSurf,
		-tileX,
		-tileY);

	    if (alpha >= 1.0) {
		cairo_paint(ctx);
	    } else {
		cairo_paint_with_alpha(ctx, alpha);
	    }

	    cairo_restore(ctx);

	}
    }
}
Beispiel #30
0
static int
xpybList_init(xpybList *self, PyObject *args, PyObject *kw)
{
    static char *kwlist[] = { "parent", "offset", "length", "type", "size", NULL };
    Py_ssize_t i, datalen, cur, offset, length, size = -1;
    PyObject *parent, *type, *obj, *arglist;
    const char *data;

    if (!PyArg_ParseTupleAndKeywords(args, kw, "OnnO|n", kwlist, &parent,
				     &offset, &length, &type, &size))
	return -1;

    self->list = PyList_New(0);
    if (self->list == NULL)
	return -1;

    if (PyObject_AsReadBuffer(parent, (const void **)&data, &datalen) < 0)
	return -1;
    if (size > 0 && length * size + offset > datalen) {
	PyErr_Format(xpybExcept_base, "Protocol object buffer too short "
		     "(expected %zd got %zd).", length * size + offset, datalen);
	return -1;
    }

    cur = offset;

    for (i = 0; i < length; i++) {
	if (PyString_CheckExact(type)) {
	    obj = xpybList_build(type, length, data + cur);
	    if (obj == NULL)
		return -1;
	    cur += size;
	} else if (size > 0) {
	    arglist = Py_BuildValue("(Onn)", parent, cur, size);
	    obj = PyEval_CallObject(type, arglist);
	    Py_DECREF(arglist);
	    if (obj == NULL)
		return -1;
	    cur += size;
	} else {
	    arglist = Py_BuildValue("(On)", parent, cur);
	    obj = PyEval_CallObject(type, arglist);
	    Py_DECREF(arglist);
	    if (obj == NULL)
		return -1;
	    datalen = PySequence_Size(obj);
	    if (datalen < 0)
		return -1;
	    cur += datalen;
	}

	if (PyList_Append(self->list, obj) < 0)
	    return -1;
        Py_DECREF(obj);
    }

    self->buf = PyBuffer_FromObject(parent, offset, cur - offset);
    if (self->buf == NULL)
	return -1;

    return 0;
}