Skip to content

Commit a7e61d4

Browse files
Add .point_size attribute modifier for fonts (#1961)
--------- Co-authored-by: Matiiss <[email protected]>
1 parent a2eac6e commit a7e61d4

File tree

6 files changed

+194
-0
lines changed

6 files changed

+194
-0
lines changed

buildconfig/stubs/pygame/font.pyi

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Font:
3535
strikethrough: bool
3636
align: int
3737
style_name: str
38+
point_size: int
3839
def __init__(self, filename: Optional[FileArg] = None, size: int = 20) -> None: ...
3940
def render(
4041
self,
@@ -62,5 +63,7 @@ class Font:
6263
def get_descent(self) -> int: ...
6364
def set_script(self, script_code: str) -> None: ...
6465
def set_direction(self, direction: int) -> None: ...
66+
def get_point_size(self) -> int: ...
67+
def set_point_size(self, val: int) -> None: ...
6568

6669
FontType = Font

docs/reST/ref/font.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,18 @@ solves no longer exists, it will likely be removed in the future.
294294

295295
.. ## Font.align ##
296296
297+
.. attribute:: point_size
298+
299+
| :sl:`Gets or sets the font's point size`
300+
| :sg:`point_size -> int`
301+
302+
Returns the point size of the font. Will not be accurate upon initializing
303+
the font object when the font name is initalized as ``None``.
304+
305+
.. versionadded:: 2.3.1
306+
307+
.. ## Font.point_size ##
308+
297309
.. method:: render
298310

299311
| :sl:`draw text on a new Surface`
@@ -509,6 +521,31 @@ solves no longer exists, it will likely be removed in the future.
509521

510522
.. ## Font.get_height ##
511523
524+
.. method:: set_point_size
525+
526+
| :sl:`set the point size of the font`
527+
| :sg:`set_point_size(size) -> int`
528+
529+
Sets the point size of the font, which is the value that was used to
530+
initalize this font.
531+
532+
.. versionadded:: 2.3.1
533+
534+
.. ## Font.set_point_size ##
535+
536+
.. method:: get_point_size
537+
538+
| :sl:`get the point size of the font`
539+
| :sg:`get_point_size() -> int`
540+
541+
Returns the point size of the font. Will not be accurate upon
542+
initializing the font object when the font name is initalized
543+
as ``None``.
544+
545+
.. versionadded:: 2.3.1
546+
547+
.. ## Font.get_point_size ##
548+
512549
.. method:: get_ascent
513550

514551
| :sl:`get the ascent of the font`

src_c/doc/font_doc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define DOC_FONT_FONT_UNDERLINE "underline -> bool\nGets or sets whether the font should be rendered with an underline."
1717
#define DOC_FONT_FONT_STRIKETHROUGH "strikethrough -> bool\nGets or sets whether the font should be rendered with a strikethrough."
1818
#define DOC_FONT_FONT_ALIGN "align -> int\nSet how rendered text is aligned when given a wrap length."
19+
#define DOC_FONT_FONT_POINTSIZE "point_size -> int\nGets or sets the font's point size"
1920
#define DOC_FONT_FONT_RENDER "render(text, antialias, color, bgcolor=None, wraplength=0) -> Surface\ndraw text on a new Surface"
2021
#define DOC_FONT_FONT_SIZE "size(text) -> (width, height)\ndetermine the amount of space needed to render text"
2122
#define DOC_FONT_FONT_SETUNDERLINE "set_underline(bool) -> None\ncontrol if text is rendered with an underline"
@@ -29,6 +30,8 @@
2930
#define DOC_FONT_FONT_GETITALIC "get_italic() -> bool\ncheck if the text will be rendered italic"
3031
#define DOC_FONT_FONT_GETLINESIZE "get_linesize() -> int\nget the line space of the font text"
3132
#define DOC_FONT_FONT_GETHEIGHT "get_height() -> int\nget the height of the font"
33+
#define DOC_FONT_FONT_SETPOINTSIZE "set_point_size(size) -> int\nset the point size of the font"
34+
#define DOC_FONT_FONT_GETPOINTSIZE "get_point_size() -> int\nget the point size of the font"
3235
#define DOC_FONT_FONT_GETASCENT "get_ascent() -> int\nget the ascent of the font"
3336
#define DOC_FONT_FONT_GETDESCENT "get_descent() -> int\nget the descent of the font"
3437
#define DOC_FONT_FONT_SETSCRIPT "set_script(str) -> None\nset the script code for text shaping"

src_c/font.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,92 @@ font_size(PyObject *self, PyObject *text)
652652
return Py_BuildValue("(ii)", w, h);
653653
}
654654

655+
static PyObject *
656+
font_getter_point_size(PyFontObject *self, void *closure)
657+
{
658+
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
659+
return PyLong_FromLong(self->ptsize);
660+
#else
661+
PyErr_SetString(pgExc_SDLError,
662+
"Incorrect SDL_TTF version (requires 2.0.18)");
663+
return NULL;
664+
#endif
665+
}
666+
667+
static int
668+
font_setter_point_size(PyFontObject *self, PyObject *value, void *closure)
669+
{
670+
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
671+
TTF_Font *font = PyFont_AsFont(self);
672+
int val = PyLong_AsLong(value);
673+
674+
if (PyErr_Occurred() && val == -1) {
675+
return -1;
676+
}
677+
678+
if (val <= 0) {
679+
PyErr_SetString(PyExc_ValueError,
680+
"point_size cannot be equal to, or less than 0");
681+
return -1;
682+
}
683+
684+
if (TTF_SetFontSize(font, val) == -1) {
685+
PyErr_SetString(pgExc_SDLError, SDL_GetError());
686+
return -1;
687+
}
688+
self->ptsize = val;
689+
690+
return 0;
691+
#else
692+
PyErr_SetString(pgExc_SDLError,
693+
"Incorrect SDL_TTF version (requires 2.0.18)");
694+
return -1;
695+
#endif
696+
}
697+
698+
static PyObject *
699+
font_get_ptsize(PyObject *self, PyObject *args)
700+
{
701+
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
702+
return PyLong_FromLong(((PyFontObject *)self)->ptsize);
703+
#else
704+
PyErr_SetString(pgExc_SDLError,
705+
"Incorrect SDL_TTF version (requires 2.0.18)");
706+
return NULL;
707+
#endif
708+
}
709+
710+
static PyObject *
711+
font_set_ptsize(PyObject *self, PyObject *arg)
712+
{
713+
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
714+
TTF_Font *font = PyFont_AsFont(self);
715+
int val = PyLong_AsLong(arg);
716+
717+
if (PyErr_Occurred() && val == -1) {
718+
return NULL;
719+
}
720+
721+
if (val <= 0) {
722+
PyErr_SetString(PyExc_ValueError,
723+
"point_size cannot be equal to, or less than 0");
724+
return NULL;
725+
}
726+
727+
if (TTF_SetFontSize(font, val) == -1) {
728+
PyErr_SetString(pgExc_SDLError, SDL_GetError());
729+
return NULL;
730+
}
731+
((PyFontObject *)self)->ptsize = val;
732+
733+
Py_RETURN_NONE;
734+
#else
735+
PyErr_SetString(pgExc_SDLError,
736+
"Incorrect SDL_TTF version (requires 2.0.18)");
737+
return NULL;
738+
#endif
739+
}
740+
655741
static PyObject *
656742
font_getter_name(PyObject *self, void *closure)
657743
{
@@ -892,6 +978,8 @@ static PyGetSetDef font_getsets[] = {
892978
(setter)font_setter_strikethrough, DOC_FONT_FONT_STRIKETHROUGH, NULL},
893979
{"align", (getter)font_getter_align, (setter)font_setter_align,
894980
DOC_FONT_FONT_ALIGN, NULL},
981+
{"point_size", (getter)font_getter_point_size,
982+
(setter)font_setter_point_size, DOC_FONT_FONT_POINTSIZE, NULL},
895983
{NULL, NULL, NULL, NULL, NULL}};
896984

897985
static PyMethodDef font_methods[] = {
@@ -911,6 +999,9 @@ static PyMethodDef font_methods[] = {
911999
DOC_FONT_FONT_GETSTRIKETHROUGH},
9121000
{"set_strikethrough", font_set_strikethrough, METH_O,
9131001
DOC_FONT_FONT_SETSTRIKETHROUGH},
1002+
{"get_point_size", font_get_ptsize, METH_NOARGS,
1003+
DOC_FONT_FONT_GETPOINTSIZE},
1004+
{"set_point_size", font_set_ptsize, METH_O, DOC_FONT_FONT_SETPOINTSIZE},
9141005
{"metrics", font_metrics, METH_O, DOC_FONT_FONT_METRICS},
9151006
{"render", (PyCFunction)font_render, METH_VARARGS | METH_KEYWORDS,
9161007
DOC_FONT_FONT_RENDER},
@@ -1024,6 +1115,7 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds)
10241115

10251116
Py_DECREF(obj);
10261117
self->font = font;
1118+
self->ptsize = fontsize;
10271119
self->ttf_init_generation = current_ttf_generation;
10281120

10291121
return 0;

src_c/include/pygame_font.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct TTF_Font;
2828
typedef struct {
2929
PyObject_HEAD TTF_Font *font;
3030
PyObject *weakreflist;
31+
int ptsize;
3132
unsigned int ttf_init_generation;
3233
} PyFontObject;
3334
#define PyFont_AsFont(x) (((PyFontObject *)x)->font)

test/font_test.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,64 @@ def test_size(self):
572572

573573
self.assertNotEqual(size, bsize)
574574

575+
def test_point_size_property(self):
576+
if pygame_font.__name__ == "pygame.ftfont":
577+
return # not a pygame.ftfont feature
578+
579+
pygame_font.init()
580+
font_path = os.path.join(
581+
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
582+
)
583+
f = pygame_font.Font(pathlib.Path(font_path), 25)
584+
585+
ttf_version = pygame_font.get_sdl_ttf_version()
586+
if ttf_version < (2, 0, 18):
587+
with self.assertRaises(pygame.error):
588+
f.point_size = 25
589+
with self.assertRaises(pygame.error):
590+
f.point_size
591+
return
592+
593+
self.assertEqual(25, f.point_size)
594+
f.point_size = 10
595+
self.assertEqual(10, f.point_size)
596+
f.point_size += 23
597+
self.assertEqual(33, f.point_size)
598+
f.point_size -= 2
599+
self.assertEqual(31, f.point_size)
600+
601+
def test_neg():
602+
f.point_size = -500
603+
604+
def test_incorrect_type():
605+
f.point_size = "15"
606+
607+
self.assertRaises(ValueError, test_neg)
608+
self.assertRaises(TypeError, test_incorrect_type)
609+
610+
def test_point_size_method(self):
611+
if pygame_font.__name__ == "pygame.ftfont":
612+
return # not a pygame.ftfont feature
613+
614+
pygame_font.init()
615+
font_path = os.path.join(
616+
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
617+
)
618+
f = pygame_font.Font(pathlib.Path(font_path), 25)
619+
620+
ttf_version = pygame_font.get_sdl_ttf_version()
621+
if ttf_version < (2, 0, 18):
622+
self.assertRaises(pygame.error, f.get_point_size)
623+
self.assertRaises(pygame.error, f.set_point_size, 25)
624+
return
625+
626+
self.assertEqual(25, f.get_point_size())
627+
f = pygame_font.Font(None, 25)
628+
f.set_point_size(10)
629+
self.assertEqual(10, f.get_point_size())
630+
self.assertRaises(ValueError, f.set_point_size, -500)
631+
self.assertRaises(TypeError, f.set_point_size, "15")
632+
575633
def test_font_name(self):
576634
f = pygame_font.Font(None, 20)
577635
self.assertEqual(f.name, "FreeSans")

0 commit comments

Comments
 (0)