-
-
Notifications
You must be signed in to change notification settings - Fork 210
Added outline property to pygame.font.Font #3597
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
8c13923
5749c32
935ab5c
0c1d1ca
df1c36d
df3f9e5
60ab8eb
75b90d8
01aacde
de2473f
90bd615
0cd38a8
05cb813
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -901,6 +901,96 @@ font_set_ptsize(PyObject *self, PyObject *arg) | |
| #endif | ||
| } | ||
|
|
||
| static PyObject * | ||
| font_getter_outline(PyObject *self, void *closure) | ||
| { | ||
| if (!PgFont_GenerationCheck(self)) { | ||
| return RAISE_FONT_QUIT_ERROR(); | ||
| } | ||
|
|
||
| #if SDL_TTF_VERSION_ATLEAST(2, 0, 12) | ||
| TTF_Font *font = PyFont_AsFont(self); | ||
| return PyLong_FromLong(TTF_GetFontOutline(font)); | ||
| #else | ||
| return RAISE(pgExc_SDLError, | ||
| "pygame.font not compiled with a new enough SDL_ttf version. " | ||
| "Needs SDL_ttf 2.0.12 or above."); | ||
| #endif | ||
| } | ||
|
|
||
| static int | ||
| font_setter_outline(PyObject *self, PyObject *value, void *closure) | ||
| { | ||
| if (!PgFont_GenerationCheck(self)) { | ||
| RAISE_FONT_QUIT_ERROR_RETURN(-1); | ||
| } | ||
| #if SDL_TTF_VERSION_ATLEAST(2, 0, 12) | ||
| TTF_Font *font = PyFont_AsFont(self); | ||
|
|
||
| DEL_ATTR_NOT_SUPPORTED_CHECK("outline", value); | ||
|
|
||
| if (!PyLong_Check(value)) { | ||
| PyErr_SetString(PyExc_TypeError, "outline must be an integer"); | ||
| return -1; | ||
| } | ||
| long val = PyLong_AsLong(value); | ||
| if (val == -1 && PyErr_Occurred()) { | ||
| return -1; | ||
| } | ||
| if (val < 0) { | ||
| PyErr_SetString(PyExc_ValueError, "outline must be >= 0"); | ||
| return -1; | ||
| } | ||
| TTF_SetFontOutline(font, (int)val); | ||
| return 0; | ||
| #else | ||
| RAISE(pgExc_SDLError, | ||
| "pygame.font not compiled with a new enough SDL_ttf version. Needs SDL_ttf 2.0.12 or above."); | ||
| return -1; | ||
| #endif | ||
| } | ||
|
|
||
| static PyObject * | ||
| font_get_outline(PyObject *self, PyObject *_null) | ||
| { | ||
| if (!PgFont_GenerationCheck(self)) { | ||
| return RAISE_FONT_QUIT_ERROR(); | ||
| } | ||
| #if SDL_TTF_VERSION_ATLEAST(2, 0, 12) | ||
| TTF_Font *font = PyFont_AsFont(self); | ||
| return PyLong_FromLong(TTF_GetFontOutline(font)); | ||
| #else | ||
| return RAISE(pgExc_SDLError, | ||
| "pygame.font not compiled with a new enough SDL_ttf version. " | ||
| "Needs SDL_ttf 2.0.12 or above."); | ||
| #endif | ||
| } | ||
|
|
||
| static PyObject * | ||
| font_set_outline(PyObject *self, PyObject *arg) | ||
| { | ||
| if (!PgFont_GenerationCheck(self)) { | ||
| return RAISE_FONT_QUIT_ERROR(); | ||
| } | ||
| #if SDL_TTF_VERSION_ATLEAST(2, 0, 12) | ||
| TTF_Font *font = PyFont_AsFont(self); | ||
| long val = PyLong_AsLong(arg); | ||
| if (val == -1 && PyErr_Occurred()) { | ||
| return NULL; | ||
| } | ||
| if (val < 0) { | ||
| return RAISE(PyExc_ValueError, "outline must be >= 0"); | ||
| } | ||
| TTF_SetFontOutline(font, (int)val); | ||
| Py_RETURN_NONE; | ||
| #else | ||
| return RAISE(pgExc_SDLError, | ||
| "pygame.font not compiled with a new enough SDL_ttf version. " | ||
| "Needs SDL_ttf 2.0.12 or above."); | ||
| #endif | ||
|
||
| } | ||
|
|
||
|
|
||
| static PyObject * | ||
| font_getter_name(PyObject *self, void *closure) | ||
| { | ||
|
|
@@ -1168,6 +1258,8 @@ static PyGetSetDef font_getsets[] = { | |
| DOC_FONT_FONT_UNDERLINE, NULL}, | ||
| {"strikethrough", (getter)font_getter_strikethrough, | ||
| (setter)font_setter_strikethrough, DOC_FONT_FONT_STRIKETHROUGH, NULL}, | ||
| {"outline", (getter)font_getter_outline, (setter)font_setter_outline, | ||
| DOC_FONT_FONT_OUTLINE, NULL}, | ||
| {"align", (getter)font_getter_align, (setter)font_setter_align, | ||
| DOC_FONT_FONT_ALIGN, NULL}, | ||
| {"point_size", (getter)font_getter_point_size, | ||
|
|
@@ -1192,6 +1284,8 @@ static PyMethodDef font_methods[] = { | |
| DOC_FONT_FONT_GETSTRIKETHROUGH}, | ||
| {"set_strikethrough", font_set_strikethrough, METH_O, | ||
| DOC_FONT_FONT_SETSTRIKETHROUGH}, | ||
| {"get_outline", font_get_outline, METH_NOARGS, DOC_FONT_FONT_GETOUTLINE}, | ||
| {"set_outline", font_set_outline, METH_O, DOC_FONT_FONT_SETOUTLINE}, | ||
| {"get_point_size", font_get_ptsize, METH_NOARGS, | ||
| DOC_FONT_FONT_GETPOINTSIZE}, | ||
| {"set_point_size", font_set_ptsize, METH_O, DOC_FONT_FONT_SETPOINTSIZE}, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -685,6 +685,70 @@ def test_point_size_method(self): | |
| self.assertRaises(ValueError, f.set_point_size, -500) | ||
| self.assertRaises(TypeError, f.set_point_size, "15") | ||
|
|
||
| def test_outline_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, 12): | ||
| with self.assertRaises(pygame.error): | ||
| f.outline = 0 | ||
| with self.assertRaises(pygame.error): | ||
| _ = f.outline | ||
| return | ||
|
||
|
|
||
| # Default outline should be an integer >= 0 (typically 0) | ||
| self.assertIsInstance(f.outline, int) | ||
| self.assertGreaterEqual(f.outline, 0) | ||
|
|
||
| orig = f.outline | ||
| f.outline = orig + 1 | ||
| self.assertEqual(orig + 1, f.outline) | ||
| f.outline += 2 | ||
| self.assertEqual(orig + 3, f.outline) | ||
| f.outline -= 1 | ||
| self.assertEqual(orig + 2, f.outline) | ||
|
|
||
| def test_neg(): | ||
| f.outline = -1 | ||
|
|
||
| def test_incorrect_type(): | ||
| f.outline = "2" | ||
|
|
||
| self.assertRaises(ValueError, test_neg) | ||
| self.assertRaises(TypeError, test_incorrect_type) | ||
|
|
||
| def test_outline_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, 12): | ||
| self.assertRaises(pygame.error, f.get_outline) | ||
| self.assertRaises(pygame.error, f.set_outline, 1) | ||
| return | ||
|
|
||
| val0 = f.get_outline() | ||
| self.assertIsInstance(val0, int) | ||
| self.assertGreaterEqual(val0, 0) | ||
|
|
||
| f.set_outline(5) | ||
| self.assertEqual(5, f.get_outline()) | ||
| self.assertRaises(ValueError, f.set_outline, -1) | ||
| self.assertRaises(TypeError, f.set_outline, "2") | ||
|
|
||
| def test_font_name(self): | ||
| f = pygame_font.Font(None, 20) | ||
| self.assertEqual(f.name, "FreeSans") | ||
|
|
@@ -933,6 +997,14 @@ def test_font_method_should_raise_exception_after_quit(self): | |
| ] | ||
| skip_methods = set() | ||
| version = pygame.font.get_sdl_ttf_version() | ||
|
|
||
| if version >= (2, 0, 12): | ||
| methods.append(("get_outline", ())) | ||
| methods.append(("set_outline", (2,))) | ||
| else: | ||
| skip_methods.add("get_outline") | ||
| skip_methods.add("set_outline") | ||
|
|
||
| if version >= (2, 0, 18): | ||
| methods.append(("get_point_size", ())) | ||
| methods.append(("set_point_size", (34,))) | ||
|
|
@@ -1032,6 +1104,11 @@ def test_font_property_should_raise_exception_after_quit(self): | |
| else: | ||
| skip_properties.add("point_size") | ||
|
|
||
| if version >= (2, 0, 12): | ||
| properties.append(("outline", 1)) | ||
| else: | ||
| skip_properties.add("outline") | ||
|
|
||
| font = pygame_font.Font(None, 10) | ||
| actual_names = [] | ||
|
|
||
|
|
@@ -1096,6 +1173,7 @@ def query( | |
| underline=False, | ||
| strikethrough=False, | ||
| antialiase=False, | ||
| outline=0 | ||
| ): | ||
| if self.aborted: | ||
| return False | ||
|
|
@@ -1106,7 +1184,7 @@ def query( | |
| screen = self.screen | ||
| screen.fill((255, 255, 255)) | ||
| pygame.display.flip() | ||
| if not (bold or italic or underline or strikethrough or antialiase): | ||
| if not (bold or italic or underline or strikethrough or antialiase or outline): | ||
| text = "normal" | ||
| else: | ||
| modes = [] | ||
|
|
@@ -1120,18 +1198,22 @@ def query( | |
| modes.append("strikethrough") | ||
| if antialiase: | ||
| modes.append("antialiased") | ||
| if outline: | ||
| modes.append("outlined") | ||
| text = f"{'-'.join(modes)} (y/n):" | ||
| f.set_bold(bold) | ||
| f.set_italic(italic) | ||
| f.set_underline(underline) | ||
| f.set_strikethrough(strikethrough) | ||
| f.set_outline(outline) | ||
| s = f.render(text, antialiase, (0, 0, 0)) | ||
| screen.blit(s, (offset, y)) | ||
| y += s.get_size()[1] + spacing | ||
| f.set_bold(False) | ||
| f.set_italic(False) | ||
| f.set_underline(False) | ||
| f.set_strikethrough(False) | ||
| f.set_outline(0) | ||
|
||
| s = f.render("(some comparison text)", False, (0, 0, 0)) | ||
| screen.blit(s, (offset, y)) | ||
| pygame.display.flip() | ||
|
|
@@ -1173,6 +1255,9 @@ def test_italic_underline(self): | |
| def test_bold_strikethrough(self): | ||
| self.assertTrue(self.query(bold=True, strikethrough=True)) | ||
|
|
||
| def test_outline(self): | ||
| self.assertTrue(self.query(outline=1)) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() | ||
Uh oh!
There was an error while loading. Please reload this page.