diff --git a/buildconfig/stubs/pygame/font.pyi b/buildconfig/stubs/pygame/font.pyi index efc72f0ae4..b05eb58cd5 100644 --- a/buildconfig/stubs/pygame/font.pyi +++ b/buildconfig/stubs/pygame/font.pyi @@ -80,6 +80,7 @@ class Font: ) -> list[tuple[int, int, int, int, int]]: ... def get_italic(self) -> bool: ... def get_linesize(self) -> int: ... + def set_linesize(self, linesize: int, /) -> None: ... def get_height(self) -> int: ... def get_ascent(self) -> int: ... def get_descent(self) -> int: ... diff --git a/docs/reST/ref/font.rst b/docs/reST/ref/font.rst index a538a48aec..33632edecf 100644 --- a/docs/reST/ref/font.rst +++ b/docs/reST/ref/font.rst @@ -511,6 +511,19 @@ solves no longer exists, it will likely be removed in the future. .. ## Font.get_linesize ## + .. method:: set_linesize + + | :sl:`set the line space of the font text` + | :sg:`set_linesize(linesize) -> None` + + Set the height in pixels for a line of text with the font. When rendering + multiple lines of text this refers to the amount of space between lines. + The value must be non-negative. + + .. versionadded:: 2.5.4 + + .. ## Font.set_linesize ## + .. method:: get_height | :sl:`get the height of the font` @@ -524,7 +537,7 @@ solves no longer exists, it will likely be removed in the future. .. method:: set_point_size | :sl:`set the point size of the font` - | :sg:`set_point_size(size, /) -> int` + | :sg:`set_point_size(size, /) -> None` Sets the point size of the font, which is the value that was used to initialize this font. diff --git a/src_c/doc/font_doc.h b/src_c/doc/font_doc.h index 64ddb16c1d..486e2d9088 100644 --- a/src_c/doc/font_doc.h +++ b/src_c/doc/font_doc.h @@ -29,8 +29,9 @@ #define DOC_FONT_FONT_METRICS "metrics(text, /) -> list\ngets the metrics for each character in the passed string" #define DOC_FONT_FONT_GETITALIC "get_italic() -> bool\ncheck if the text will be rendered italic" #define DOC_FONT_FONT_GETLINESIZE "get_linesize() -> int\nget the line space of the font text" +#define DOC_FONT_FONT_SETLINESIZE "set_linesize(linesize) -> None\nset the line space of the font text" #define DOC_FONT_FONT_GETHEIGHT "get_height() -> int\nget the height of the font" -#define DOC_FONT_FONT_SETPOINTSIZE "set_point_size(size, /) -> int\nset the point size of the font" +#define DOC_FONT_FONT_SETPOINTSIZE "set_point_size(size, /) -> None\nset the point size of the font" #define DOC_FONT_FONT_GETPOINTSIZE "get_point_size() -> int\nget the point size of the font" #define DOC_FONT_FONT_GETASCENT "get_ascent() -> int\nget the ascent of the font" #define DOC_FONT_FONT_GETDESCENT "get_descent() -> int\nget the descent of the font" diff --git a/src_c/font.c b/src_c/font.c index ee97747222..7842d225a2 100644 --- a/src_c/font.c +++ b/src_c/font.c @@ -226,6 +226,38 @@ font_get_linesize(PyObject *self, PyObject *_null) #endif } +static PyObject * +font_set_linesize(PyObject *self, PyObject *arg) +{ + if (!PgFont_GenerationCheck(self)) { + return RAISE_FONT_QUIT_ERROR(); + } + +#if SDL_TTF_VERSION_ATLEAST(2, 24, 0) + TTF_Font *font = PyFont_AsFont(self); + + if (!PyLong_Check(arg)) { + return RAISE(PyExc_TypeError, "linesize must be an integer"); + } + int linesize = PyLong_AsLong(arg); + if (linesize == -1 && PyErr_Occurred()) { + return NULL; + } + + if (linesize < 0) { + return RAISE(PyExc_ValueError, "linesize must be >= 0"); + } + + TTF_SetFontLineSkip(font, linesize); + + Py_RETURN_NONE; +#else + return RAISE( + PyExc_NotImplementedError, + "TTF_SetFontLineSkip is not available in this version of SDL_ttf"); +#endif +} + static PyObject * _font_get_style_flag_as_py_bool(PyObject *self, int flag) { @@ -1155,6 +1187,7 @@ static PyMethodDef font_methods[] = { {"get_ascent", font_get_ascent, METH_NOARGS, DOC_FONT_FONT_GETASCENT}, {"get_linesize", font_get_linesize, METH_NOARGS, DOC_FONT_FONT_GETLINESIZE}, + {"set_linesize", font_set_linesize, METH_O, DOC_FONT_FONT_SETLINESIZE}, {"get_bold", font_get_bold, METH_NOARGS, DOC_FONT_FONT_GETBOLD}, {"set_bold", font_set_bold, METH_O, DOC_FONT_FONT_SETBOLD}, {"get_italic", font_get_italic, METH_NOARGS, DOC_FONT_FONT_GETITALIC}, diff --git a/test/font_test.py b/test/font_test.py index f008da2e69..3e236d52e0 100644 --- a/test/font_test.py +++ b/test/font_test.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -import sys -import os import io -import unittest +import os import pathlib import platform +import sys +import unittest import pygame from pygame import font as pygame_font # So font can be replaced with ftfont @@ -385,6 +385,35 @@ def test_get_linesize(self): self.assertTrue(isinstance(linesize, int)) self.assertTrue(linesize > 0) + @unittest.skipIf( + pygame.font.get_sdl_ttf_version() < (2, 24, 0), + "supported in SDL_ttf 2.24.0 onwards", + ) + def test_set_linesize(self): + if pygame_font.__name__ == "pygame.ftfont": + return # not a pygame.ftfont thing + + f = pygame_font.Font(None, 20) + linesize = f.get_linesize() + + # check increasing linesize + f.set_linesize(linesize + 1) + self.assertEqual(f.get_linesize(), linesize + 1) + + # check random linesize + expected_linesizes = [30, 1, 22, 34, 5, 10, 0] + for expected_size in expected_linesizes: + f.set_linesize(expected_size) + self.assertEqual(f.get_linesize(), expected_size) + + # check invalid linesize + with self.assertRaises(ValueError): + f.set_linesize(-1) + with self.assertRaises(OverflowError): + f.set_linesize(2**100) + with self.assertRaises(TypeError): + f.set_linesize(12.0) + def test_metrics(self): # Ensure bytes decoding works correctly. Can only compare results # with unicode for now. @@ -906,6 +935,11 @@ def test_font_method_should_raise_exception_after_quit(self): skip_methods.add("set_point_size") skip_methods.add("point_size") + if version >= (2, 24, 0): + methods.append(("set_linesize", (2,))) + else: + skip_methods.add("set_linesize") + if version < (2, 20, 0): skip_methods.add("align")