File: pythontiledsurface.cpp

package info (click to toggle)
mypaint 2.0.1-12
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 27,844 kB
  • sloc: python: 43,893; cpp: 6,931; xml: 2,475; sh: 473; makefile: 25
file content (96 lines) | stat: -rw-r--r-- 2,865 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/* This file is part of MyPaint.
 * Copyright (C) 2008-2011 by Martin Renold <martinxyz@gmx.ch>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include "pythontiledsurface.h"
#include "surface.hpp"

#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#define NO_IMPORT_ARRAY
#include <numpy/arrayobject.h>
#include <numpy/ndarraytypes.h>

#include <mypaint-tiled-surface.h>


struct MyPaintPythonTiledSurface {
    MyPaintTiledSurface2 parent;
    PyObject * py_obj;
};

// Forward declare
void free_tiledsurf(MyPaintSurface *surface);

static void
tile_request_start(MyPaintTiledSurface2 *tiled_surface, MyPaintTileRequest *request)
{
    MyPaintPythonTiledSurface *self = (MyPaintPythonTiledSurface *)tiled_surface;

    const gboolean readonly = request->readonly;
    const int tx = request->tx;
    const int ty = request->ty;
    PyArrayObject* rgba = NULL;

{
    PyGILState_STATE gstate = PyGILState_Ensure();

    rgba = (PyArrayObject*)PyObject_CallMethod(self->py_obj, "_get_tile_numpy", "(iii)", tx, ty, readonly);
    if (rgba == NULL) {
        request->buffer = NULL;
        printf("Python exception during get_tile_numpy()!\n");
        if (PyErr_Occurred()) {
            PyErr_Print();
        }
    } else {

#ifdef HEAVY_DEBUG
        assert(PyArray_NDIM(rgba) == 3);
        assert(PyArray_DIM(rgba, 0) == tiled_surface->tile_size);
        assert(PyArray_DIM(rgba, 1) == tiled_surface->tile_size);
        assert(PyArray_DIM(rgba, 2) == 4);
        assert(PyArray_ISCARRAY(rgba));
        assert(PyArray_TYPE(rgba) == NPY_UINT16);
#endif
        // tiledsurface.py will keep a reference in its tiledict, at least until the final end_atomic()
        Py_DECREF((PyObject *)rgba);
        request->buffer = (uint16_t*)PyArray_DATA(rgba);
    }

    PyGILState_Release(gstate);
}


}

static void
tile_request_end(MyPaintTiledSurface2 *tiled_surface, MyPaintTileRequest *request)
{
    // We modify tiles directly, so don't need to do anything here
}

MyPaintPythonTiledSurface *
mypaint_python_tiled_surface_new(PyObject *py_object)
{
    MyPaintPythonTiledSurface *self = (MyPaintPythonTiledSurface *)malloc(sizeof(MyPaintPythonTiledSurface));

    mypaint_tiled_surface2_init(&self->parent, tile_request_start, tile_request_end);
    self->parent.threadsafe_tile_requests = TRUE;

    // MyPaintSurface vfuncs
    self->parent.parent.parent.destroy = free_tiledsurf;
    self->py_obj = py_object; // no need to incref

    return self;
}

void free_tiledsurf(MyPaintSurface *surface)
{
    MyPaintPythonTiledSurface *self = (MyPaintPythonTiledSurface *)surface;
    mypaint_tiled_surface2_destroy(&self->parent);
    free(self);
}