diff --git a/buildconfig/stubs/pygame/__init__.pyi b/buildconfig/stubs/pygame/__init__.pyi index bf79ffaf71..254c04f431 100644 --- a/buildconfig/stubs/pygame/__init__.pyi +++ b/buildconfig/stubs/pygame/__init__.pyi @@ -597,6 +597,10 @@ from .constants import ( K_y as K_y, K_z as K_z, LIL_ENDIAN as LIL_ENDIAN, + LINE_RENDER_DEFAULT as LINE_RENDER_DEFAULT, + LINE_RENDER_GEOMETRY as LINE_RENDER_GEOMETRY, + LINE_RENDER_LINE as LINE_RENDER_LINE, + LINE_RENDER_POINT as LINE_RENDER_POINT, LOCALECHANGED as LOCALECHANGED, MIDIIN as MIDIIN, MIDIOUT as MIDIOUT, diff --git a/buildconfig/stubs/pygame/_render.pyi b/buildconfig/stubs/pygame/_render.pyi index 907bda2601..60352cb0ca 100644 --- a/buildconfig/stubs/pygame/_render.pyi +++ b/buildconfig/stubs/pygame/_render.pyi @@ -146,3 +146,6 @@ class Texture: @final class Image: pass + +def get_line_render_method() -> int: ... +def set_line_render_method(method: int) -> bool: ... diff --git a/buildconfig/stubs/pygame/constants.pyi b/buildconfig/stubs/pygame/constants.pyi index 044d9534fa..6382b5cf6a 100644 --- a/buildconfig/stubs/pygame/constants.pyi +++ b/buildconfig/stubs/pygame/constants.pyi @@ -519,6 +519,10 @@ K_x: int K_y: int K_z: int LIL_ENDIAN: int +LINE_RENDER_DEFAULT: int +LINE_RENDER_GEOMETRY: int +LINE_RENDER_LINE: int +LINE_RENDER_POINT: int LOCALECHANGED: int MIDIIN: int MIDIOUT: int @@ -1191,4 +1195,8 @@ __all__ = [ "FLASH_CANCEL", "FLASH_BRIEFLY", "FLASH_UNTIL_FOCUSED", + "LINE_RENDER_DEFAULT", + "LINE_RENDER_POINT", + "LINE_RENDER_LINE", + "LINE_RENDER_GEOMETRY", ] diff --git a/buildconfig/stubs/pygame/locals.pyi b/buildconfig/stubs/pygame/locals.pyi index 95b838fa80..89c3836310 100644 --- a/buildconfig/stubs/pygame/locals.pyi +++ b/buildconfig/stubs/pygame/locals.pyi @@ -520,6 +520,10 @@ K_x: int K_y: int K_z: int LIL_ENDIAN: int +LINE_RENDER_DEFAULT: int +LINE_RENDER_GEOMETRY: int +LINE_RENDER_LINE: int +LINE_RENDER_POINT: int LOCALECHANGED: int MIDIIN: int MIDIOUT: int @@ -1193,6 +1197,10 @@ __all__ = [ "FLASH_CANCEL", "FLASH_BRIEFLY", "FLASH_UNTIL_FOCUSED", + "LINE_RENDER_DEFAULT", + "LINE_RENDER_POINT", + "LINE_RENDER_LINE", + "LINE_RENDER_GEOMETRY", "Rect", "Color", ] diff --git a/src_c/constants.c b/src_c/constants.c index 3ed987be38..d212fed75c 100644 --- a/src_c/constants.c +++ b/src_c/constants.c @@ -671,6 +671,11 @@ MODINIT_DEFINE(constants) DEC_CONSTS(FLASH_UNTIL_FOCUSED, -1); #endif + DEC_CONSTS(LINE_RENDER_DEFAULT, 0) + DEC_CONSTS(LINE_RENDER_POINT, 1) + DEC_CONSTS(LINE_RENDER_LINE, 2) + DEC_CONSTS(LINE_RENDER_GEOMETRY, 3) + if (PyModule_AddObject(module, "__all__", all_list)) { Py_DECREF(all_list); Py_DECREF(module); diff --git a/src_c/render.c b/src_c/render.c index a994665d1b..e1b65a852f 100644 --- a/src_c/render.c +++ b/src_c/render.c @@ -1183,6 +1183,56 @@ image_renderer_draw(pgImageObject *self, PyObject *area, PyObject *dest) return 1; } +#if (SDL_VERSION_ATLEAST(2, 0, 20) && !SDL_VERSION_ATLEAST(3, 0, 0)) || SDL_VERSION_ATLEAST(3, 2, 0) +static PyObject * +get_line_render_method(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + const char *hint = SDL_GetHint(SDL_HINT_RENDER_LINE_METHOD); + return PyLong_FromLong( + hint == NULL ? 0 : hint[0] - '0'); // hint is a char between 0-3 +} + +static PyObject * +set_line_render_method(PyObject *self, PyObject *args) +{ + int method; + if (!PyArg_ParseTuple(args, "i", &method)) { + return NULL; + } + if (method < 0 || 3 < method) { + return RAISE(PyExc_ValueError, + "Invalid line render method: must be between" + " 0 and 3 (use LINE_RENDER_* constants)"); + } + + // SDL_SetHint expects the method as a string + char hint[2]; + hint[0] = method + '0'; // ascii char manipulation + hint[1] = '\0'; + + if (SDL_SetHint(SDL_HINT_RENDER_LINE_METHOD, hint)) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} +#else +static PyObject * +get_line_render_method(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return RAISE(PyExc_NotImplementedError, "Setting/getting the " + "line render method is only available when built with SDL2 2.0.20" + " or SDL3 3.2.0") +} + +static PyObject * +set_line_render_method(PyObject *self, PyObject *args) +{ + return RAISE(PyExc_NotImplementedError, "Setting/getting the " + "line render method is only available when built with SDL2 2.0.20" + " or SDL3 3.2.0") +} +#endif + /* Module definition */ static PyMethodDef renderer_methods[] = { {"draw_point", (PyCFunction)renderer_draw_point, @@ -1307,7 +1357,13 @@ static PyTypeObject pgImage_Type = { //.tp_init = (initproc)image_init, .tp_new = PyType_GenericNew, .tp_getset = image_getset}; -static PyMethodDef _render_methods[] = {{NULL, NULL, 0, NULL}}; +static PyMethodDef _render_methods[] = { + {"get_line_render_method", (PyCFunction)get_line_render_method, + METH_NOARGS, NULL}, + {"set_line_render_method", (PyCFunction)set_line_render_method, + METH_VARARGS, NULL}, + + {NULL, NULL, 0, NULL}}; MODINIT_DEFINE(_render) { diff --git a/test/render_test.py b/test/render_test.py index 112e93786a..916a2f8895 100644 --- a/test/render_test.py +++ b/test/render_test.py @@ -482,3 +482,29 @@ def test_update(self): result = self.renderer.to_surface() for x in range(25, 75): self.assertEqual(pygame.Color(80, 120, 160, 255), result.get_at((x, 50))) + + +class LineRenderMethodTest(unittest.TestCase): + def test_correct_argument(self): + with self.assertRaises(ValueError): + _render.set_line_render_method(-1) + with self.assertRaises(ValueError): + _render.set_line_render_method(10) + with self.assertRaises(ValueError): + _render.set_line_render_method("foo") + with self.assertRaises(ValueError): + _render.set_line_render_method(None) + + def test_get_set_line_render_method(self): + if _render.set_line_render_method(pygame.LINE_RENDER_DEFAULT): + self.assertEqual( + pygame.LINE_RENDER_DEFAULT, _render.get_line_render_method() + ) + if _render.set_line_render_method(pygame.LINE_RENDER_POINT): + self.assertEqual(pygame.LINE_RENDER_POINT, _render.get_line_render_method()) + if _render.set_line_render_method(pygame.LINE_RENDER_LINE): + self.assertEqual(pygame.LINE_RENDER_LINE, _render.get_line_render_method()) + if _render.set_line_render_method(pygame.LINE_RENDER_GEOMETRY): + self.assertEqual( + pygame.LINE_RENDER_GEOMETRY, _render.get_line_render_method() + )