Skip to content

Commit

Permalink
Add .point_size attribute modifier for fonts (#1961)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Matiiss <[email protected]>
  • Loading branch information
novialriptide and Matiiss authored Jul 30, 2023
1 parent a2eac6e commit a7e61d4
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 0 deletions.
3 changes: 3 additions & 0 deletions buildconfig/stubs/pygame/font.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Font:
strikethrough: bool
align: int
style_name: str
point_size: int
def __init__(self, filename: Optional[FileArg] = None, size: int = 20) -> None: ...
def render(
self,
Expand Down Expand Up @@ -62,5 +63,7 @@ class Font:
def get_descent(self) -> int: ...
def set_script(self, script_code: str) -> None: ...
def set_direction(self, direction: int) -> None: ...
def get_point_size(self) -> int: ...
def set_point_size(self, val: int) -> None: ...

FontType = Font
37 changes: 37 additions & 0 deletions docs/reST/ref/font.rst
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,18 @@ solves no longer exists, it will likely be removed in the future.

.. ## Font.align ##
.. attribute:: point_size

| :sl:`Gets or sets the font's point size`
| :sg:`point_size -> int`
Returns the point size of the font. Will not be accurate upon initializing
the font object when the font name is initalized as ``None``.

.. versionadded:: 2.3.1

.. ## Font.point_size ##
.. method:: render

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

.. ## Font.get_height ##
.. method:: set_point_size

| :sl:`set the point size of the font`
| :sg:`set_point_size(size) -> int`
Sets the point size of the font, which is the value that was used to
initalize this font.

.. versionadded:: 2.3.1

.. ## Font.set_point_size ##
.. method:: get_point_size

| :sl:`get the point size of the font`
| :sg:`get_point_size() -> int`
Returns the point size of the font. Will not be accurate upon
initializing the font object when the font name is initalized
as ``None``.

.. versionadded:: 2.3.1

.. ## Font.get_point_size ##
.. method:: get_ascent

| :sl:`get the ascent of the font`
Expand Down
3 changes: 3 additions & 0 deletions src_c/doc/font_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define DOC_FONT_FONT_UNDERLINE "underline -> bool\nGets or sets whether the font should be rendered with an underline."
#define DOC_FONT_FONT_STRIKETHROUGH "strikethrough -> bool\nGets or sets whether the font should be rendered with a strikethrough."
#define DOC_FONT_FONT_ALIGN "align -> int\nSet how rendered text is aligned when given a wrap length."
#define DOC_FONT_FONT_POINTSIZE "point_size -> int\nGets or sets the font's point size"
#define DOC_FONT_FONT_RENDER "render(text, antialias, color, bgcolor=None, wraplength=0) -> Surface\ndraw text on a new Surface"
#define DOC_FONT_FONT_SIZE "size(text) -> (width, height)\ndetermine the amount of space needed to render text"
#define DOC_FONT_FONT_SETUNDERLINE "set_underline(bool) -> None\ncontrol if text is rendered with an underline"
Expand All @@ -29,6 +30,8 @@
#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_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_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"
#define DOC_FONT_FONT_SETSCRIPT "set_script(str) -> None\nset the script code for text shaping"
Expand Down
92 changes: 92 additions & 0 deletions src_c/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,92 @@ font_size(PyObject *self, PyObject *text)
return Py_BuildValue("(ii)", w, h);
}

static PyObject *
font_getter_point_size(PyFontObject *self, void *closure)
{
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
return PyLong_FromLong(self->ptsize);
#else
PyErr_SetString(pgExc_SDLError,
"Incorrect SDL_TTF version (requires 2.0.18)");
return NULL;
#endif
}

static int
font_setter_point_size(PyFontObject *self, PyObject *value, void *closure)
{
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
TTF_Font *font = PyFont_AsFont(self);
int val = PyLong_AsLong(value);

if (PyErr_Occurred() && val == -1) {
return -1;
}

if (val <= 0) {
PyErr_SetString(PyExc_ValueError,
"point_size cannot be equal to, or less than 0");
return -1;
}

if (TTF_SetFontSize(font, val) == -1) {
PyErr_SetString(pgExc_SDLError, SDL_GetError());
return -1;
}
self->ptsize = val;

return 0;
#else
PyErr_SetString(pgExc_SDLError,
"Incorrect SDL_TTF version (requires 2.0.18)");
return -1;
#endif
}

static PyObject *
font_get_ptsize(PyObject *self, PyObject *args)
{
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
return PyLong_FromLong(((PyFontObject *)self)->ptsize);
#else
PyErr_SetString(pgExc_SDLError,
"Incorrect SDL_TTF version (requires 2.0.18)");
return NULL;
#endif
}

static PyObject *
font_set_ptsize(PyObject *self, PyObject *arg)
{
#if SDL_TTF_VERSION_ATLEAST(2, 0, 18)
TTF_Font *font = PyFont_AsFont(self);
int val = PyLong_AsLong(arg);

if (PyErr_Occurred() && val == -1) {
return NULL;
}

if (val <= 0) {
PyErr_SetString(PyExc_ValueError,
"point_size cannot be equal to, or less than 0");
return NULL;
}

if (TTF_SetFontSize(font, val) == -1) {
PyErr_SetString(pgExc_SDLError, SDL_GetError());
return NULL;
}
((PyFontObject *)self)->ptsize = val;

Py_RETURN_NONE;
#else
PyErr_SetString(pgExc_SDLError,
"Incorrect SDL_TTF version (requires 2.0.18)");
return NULL;
#endif
}

static PyObject *
font_getter_name(PyObject *self, void *closure)
{
Expand Down Expand Up @@ -892,6 +978,8 @@ static PyGetSetDef font_getsets[] = {
(setter)font_setter_strikethrough, DOC_FONT_FONT_STRIKETHROUGH, NULL},
{"align", (getter)font_getter_align, (setter)font_setter_align,
DOC_FONT_FONT_ALIGN, NULL},
{"point_size", (getter)font_getter_point_size,
(setter)font_setter_point_size, DOC_FONT_FONT_POINTSIZE, NULL},
{NULL, NULL, NULL, NULL, NULL}};

static PyMethodDef font_methods[] = {
Expand All @@ -911,6 +999,9 @@ static PyMethodDef font_methods[] = {
DOC_FONT_FONT_GETSTRIKETHROUGH},
{"set_strikethrough", font_set_strikethrough, METH_O,
DOC_FONT_FONT_SETSTRIKETHROUGH},
{"get_point_size", font_get_ptsize, METH_NOARGS,
DOC_FONT_FONT_GETPOINTSIZE},
{"set_point_size", font_set_ptsize, METH_O, DOC_FONT_FONT_SETPOINTSIZE},
{"metrics", font_metrics, METH_O, DOC_FONT_FONT_METRICS},
{"render", (PyCFunction)font_render, METH_VARARGS | METH_KEYWORDS,
DOC_FONT_FONT_RENDER},
Expand Down Expand Up @@ -1024,6 +1115,7 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds)

Py_DECREF(obj);
self->font = font;
self->ptsize = fontsize;
self->ttf_init_generation = current_ttf_generation;

return 0;
Expand Down
1 change: 1 addition & 0 deletions src_c/include/pygame_font.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct TTF_Font;
typedef struct {
PyObject_HEAD TTF_Font *font;
PyObject *weakreflist;
int ptsize;
unsigned int ttf_init_generation;
} PyFontObject;
#define PyFont_AsFont(x) (((PyFontObject *)x)->font)
Expand Down
58 changes: 58 additions & 0 deletions test/font_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,64 @@ def test_size(self):

self.assertNotEqual(size, bsize)

def test_point_size_property(self):
if pygame_font.__name__ == "pygame.ftfont":
return # not a pygame.ftfont feature

pygame_font.init()
font_path = os.path.join(
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
)
f = pygame_font.Font(pathlib.Path(font_path), 25)

ttf_version = pygame_font.get_sdl_ttf_version()
if ttf_version < (2, 0, 18):
with self.assertRaises(pygame.error):
f.point_size = 25
with self.assertRaises(pygame.error):
f.point_size
return

self.assertEqual(25, f.point_size)
f.point_size = 10
self.assertEqual(10, f.point_size)
f.point_size += 23
self.assertEqual(33, f.point_size)
f.point_size -= 2
self.assertEqual(31, f.point_size)

def test_neg():
f.point_size = -500

def test_incorrect_type():
f.point_size = "15"

self.assertRaises(ValueError, test_neg)
self.assertRaises(TypeError, test_incorrect_type)

def test_point_size_method(self):
if pygame_font.__name__ == "pygame.ftfont":
return # not a pygame.ftfont feature

pygame_font.init()
font_path = os.path.join(
os.path.split(pygame.__file__)[0], pygame_font.get_default_font()
)
f = pygame_font.Font(pathlib.Path(font_path), 25)

ttf_version = pygame_font.get_sdl_ttf_version()
if ttf_version < (2, 0, 18):
self.assertRaises(pygame.error, f.get_point_size)
self.assertRaises(pygame.error, f.set_point_size, 25)
return

self.assertEqual(25, f.get_point_size())
f = pygame_font.Font(None, 25)
f.set_point_size(10)
self.assertEqual(10, f.get_point_size())
self.assertRaises(ValueError, f.set_point_size, -500)
self.assertRaises(TypeError, f.set_point_size, "15")

def test_font_name(self):
f = pygame_font.Font(None, 20)
self.assertEqual(f.name, "FreeSans")
Expand Down

0 comments on commit a7e61d4

Please sign in to comment.