@@ -540,28 +540,11 @@ font_set_strikethrough(PyObject *self, PyObject *arg)
540540
541541static int
542542_create_font_surface (TTF_Font * font , PyObject * text , int antialias ,
543- PyObject * fg_rgba_obj , PyObject * bg_rgba_obj ,
543+ SDL_Color foreg , SDL_Color backg , int draw_backg ,
544544 int wraplength , SDL_Surface * * dst_surf )
545545{
546- Uint8 rgba [] = {0 , 0 , 0 , 0 };
547546 const char * astring = "" ;
548547
549- // 글꼴 생성
550- if (!pg_RGBAFromObjEx (fg_rgba_obj , rgba , PG_COLOR_HANDLE_ALL )) {
551- return 0 ; // exception already set
552- }
553-
554- SDL_Color foreg = {rgba [0 ], rgba [1 ], rgba [2 ], SDL_ALPHA_OPAQUE };
555- /* might be overridden right below, with an explicit background color */
556- SDL_Color backg = {0 , 0 , 0 , SDL_ALPHA_OPAQUE };
557-
558- if (bg_rgba_obj != Py_None ) {
559- if (!pg_RGBAFromObjEx (bg_rgba_obj , rgba , PG_COLOR_HANDLE_ALL )) {
560- return 0 ; // exception already set.
561- }
562- backg = (SDL_Color ){rgba [0 ], rgba [1 ], rgba [2 ], SDL_ALPHA_OPAQUE };
563- }
564-
565548 if (!PyUnicode_Check (text ) && !PyBytes_Check (text ) && text != Py_None ) {
566549 PyErr_Format (PyExc_TypeError , "text must be a unicode or bytes" );
567550 return 0 ;
@@ -602,7 +585,7 @@ _create_font_surface(TTF_Font *font, PyObject *text, int antialias,
602585 * dst_surf = PG_CreateSurface (0 , height , PG_PIXELFORMAT_XRGB8888 );
603586 }
604587 else { /* normal case */
605- if (antialias && bg_rgba_obj == Py_None ) {
588+ if (antialias && ! draw_backg ) {
606589#if SDL_TTF_VERSION_ATLEAST (2 , 0 , 18 )
607590 * dst_surf = TTF_RenderUTF8_Blended_Wrapped (font , astring , foreg ,
608591 wraplength );
@@ -627,7 +610,7 @@ _create_font_surface(TTF_Font *font, PyObject *text, int antialias,
627610#endif
628611 /* If an explicit background was provided and the rendering options
629612 resolve to Render_Solid, that needs to be explicitly handled. */
630- if (* dst_surf != NULL && bg_rgba_obj != Py_None ) {
613+ if (* dst_surf != NULL && draw_backg ) {
631614 SDL_SetColorKey (* dst_surf , 0 , 0 );
632615 (* dst_surf )-> format -> palette -> colors [0 ].r = backg .r ;
633616 (* dst_surf )-> format -> palette -> colors [0 ].g = backg .g ;
@@ -655,8 +638,12 @@ font_render(PyObject *self, PyObject *args, PyObject *kwds)
655638 PyObject * text , * final ;
656639 PyObject * fg_rgba_obj , * bg_rgba_obj = Py_None ;
657640 SDL_Surface * surf = NULL ;
641+ SDL_Surface * outline_surf = NULL ;
658642 int wraplength = 0 ;
659643 TTF_Font * font = PyFont_AsFont (self );
644+ int outline_size = ((PyFontObject * )self )-> outline_size ;
645+ SDL_Color outline_color = ((PyFontObject * )self )-> outline_color ;
646+ Uint8 rgba [] = {0 , 0 , 0 , 0 };
660647
661648 if (!PgFont_GenerationCheck (self )) {
662649 return RAISE_FONT_QUIT_ERROR ()
@@ -671,14 +658,74 @@ font_render(PyObject *self, PyObject *args, PyObject *kwds)
671658 return NULL ;
672659 }
673660
674- if (!_create_font_surface (font , text , antialias , fg_rgba_obj , bg_rgba_obj ,
661+ // 글꼴 생성
662+ if (!pg_RGBAFromObjEx (fg_rgba_obj , rgba , PG_COLOR_HANDLE_ALL )) {
663+ return 0 ; // exception already set
664+ }
665+
666+ SDL_Color foreg = {rgba [0 ], rgba [1 ], rgba [2 ], SDL_ALPHA_OPAQUE };
667+ SDL_Color backg = {0 , 0 , 0 , SDL_ALPHA_OPAQUE };
668+ int draw_backg = 1 ;
669+ /* might be overridden right below, with an explicit background color */
670+
671+ if (bg_rgba_obj != Py_None ) {
672+ if (!pg_RGBAFromObjEx (bg_rgba_obj , rgba , PG_COLOR_HANDLE_ALL )) {
673+ return 0 ; // exception already set.
674+ }
675+ backg = (SDL_Color ){rgba [0 ], rgba [1 ], rgba [2 ], SDL_ALPHA_OPAQUE };
676+ }
677+ else {
678+ draw_backg = 0 ;
679+ }
680+
681+ if (!_create_font_surface (font , text , antialias , foreg , backg , draw_backg ,
675682 wraplength , & surf )) {
676683 return NULL ;
677684 }
678685
679- final = (PyObject * )pgSurface_New (surf );
686+ SDL_Surface * filled_with_outline_surf = NULL ;
687+
688+ if (outline_size > 0 ) {
689+ TTF_SetFontOutline (font , outline_size );
690+
691+ if (!_create_font_surface (font , text , antialias , outline_color , backg ,
692+ draw_backg , wraplength , & outline_surf )) {
693+ return NULL ;
694+ }
695+
696+ TTF_SetFontOutline (font , 0 );
697+
698+ filled_with_outline_surf = PG_CreateSurface (
699+ outline_surf -> w , outline_surf -> h , SDL_PIXELFORMAT_RGBA32 );
700+
701+ // `surf` and `outline_surf` are **NOT** the same size.
702+ SDL_Rect outlinerect ;
703+ outlinerect .x = filled_with_outline_surf -> w / 2 - outline_surf -> w / 2 ;
704+ outlinerect .y = filled_with_outline_surf -> h / 2 - outline_surf -> h / 2 ;
705+ outlinerect .w = outline_surf -> w ;
706+ outlinerect .h = outline_surf -> h ;
707+ SDL_Rect fillrect ;
708+ fillrect .x = filled_with_outline_surf -> w / 2 - surf -> w / 2 ;
709+ fillrect .y = filled_with_outline_surf -> h / 2 - surf -> h / 2 ;
710+ fillrect .w = surf -> w ;
711+ fillrect .h = surf -> h ;
712+ SDL_BlitSurface (surf , NULL , filled_with_outline_surf , & fillrect );
713+ SDL_BlitSurface (outline_surf , NULL , filled_with_outline_surf ,
714+ & outlinerect );
715+
716+ final = (PyObject * )pgSurface_New (filled_with_outline_surf );
717+ }
718+ else {
719+ final = (PyObject * )pgSurface_New (surf );
720+ }
721+
680722 if (final == NULL ) {
681723 SDL_FreeSurface (surf );
724+ if (outline_surf != NULL )
725+ SDL_FreeSurface (outline_surf );
726+
727+ if (filled_with_outline_surf != NULL )
728+ SDL_FreeSurface (filled_with_outline_surf );
682729 }
683730 return final ;
684731}
@@ -1309,6 +1356,9 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds)
13091356 Py_DECREF (obj );
13101357 self -> font = font ;
13111358 self -> ptsize = fontsize ;
1359+ self -> outline_size = 0 ;
1360+ SDL_Color init_color = {0 , 0 , 0 , SDL_ALPHA_OPAQUE };
1361+ self -> outline_color = init_color ;
13121362 self -> ttf_init_generation = current_ttf_generation ;
13131363
13141364 return 0 ;
0 commit comments