Commits

Lenard Lindstrom committed 3f25a2e

Fix _freetype module autoquit problem

The _freetype quit function was registered with Pygame only once, in the
module's init function. Calling Pygame.quit() closed the _freetype module,
but also cleared the list of registered quit functions. So if Pygame.init()
and Pygame.quit() where called again, the _freetype autoinit functions was
called, but no quit function was registered for Pygame.quit(), and so
_freetype remained initialized. This fix has the _freetype autoinit function
register the autoquit.

Comments (0)

Files changed (2)

 static PyObject *_ft_get_error(PyObject *);
 static PyObject *_ft_was_init(PyObject *);
 static PyObject *_ft_autoinit(PyObject *);
+static void _ft_autoquit(void);
 static PyObject *_ft_get_default_resolution(PyObject *);
 static PyObject *_ft_set_default_resolution(PyObject *, PyObject *);
 static PyObject *_ft_get_default_font(PyObject* self);
     FT_Error result = 1;
 
     if (!FREETYPE_MOD_STATE(self)->freetype) {
+        PyGame_RegisterQuit(_ft_autoquit);
+
         if (_PGFT_Init(&(FREETYPE_MOD_STATE(self)->freetype),
                        FREETYPE_MOD_STATE(self)->cache_size)) {
             return 0;
     return PyInt_FromLong(result);
 }
 
+static void
+_ft_autoquit(void)
+{
+    _FreeTypeState *state = FREETYPE_STATE;
+
+    if (state->freetype) {
+        _PGFT_Quit(state->freetype);
+        state->freetype = 0;
+    }
+}
+
 static PyObject *
 _ft_quit(PyObject *self)
 {
-    if (FREETYPE_MOD_STATE(self)->freetype) {
-        _PGFT_Quit(FREETYPE_MOD_STATE(self)->freetype);
-        FREETYPE_MOD_STATE(self)->freetype = 0;
-    }
+    _ft_autoquit();
     Py_RETURN_NONE;
 }
 
 
 MODINIT_DEFINE (_freetype)
 {
-    PyObject *module, *apiobj, *pygame, *pygame_register_quit, *quit, *rval;
+    PyObject *module, *apiobj;
     static void* c_api[PYGAMEAPI_FREETYPE_NUMSLOTS];
 
     import_pygame_base();
         MODINIT_ERROR;
     }
 
-    /* import needed modules. Do this first so if there is an error
-       the module is not loaded.
-    */
-    pygame = PyImport_ImportModule ("pygame");
-    if (!pygame) {
-        MODINIT_ERROR;
-    }
-    pygame_register_quit = PyObject_GetAttrString (pygame, "register_quit");
-    Py_DECREF (pygame);
-    if (!pygame_register_quit) {
-        MODINIT_ERROR;
-    }
-
     /* type preparation */
     if (PyType_Ready(&PgFace_Type) < 0)  {
-        Py_DECREF(pygame_register_quit);
         MODINIT_ERROR;
     }
 
 #endif
 
     if (!module)  {
-        Py_DECREF(pygame_register_quit);
         MODINIT_ERROR;
     }
 
     Py_INCREF((PyObject *)&PgFace_Type);
     if (PyModule_AddObject(module, FACE_TYPE_NAME,
                            (PyObject *)&PgFace_Type) == -1)  {
-        Py_DECREF(pygame_register_quit);
         Py_DECREF((PyObject *) &PgFace_Type);
         DECREF_MOD(module);
         MODINIT_ERROR;
 
     apiobj = encapsulate_api(c_api, "freetype");
     if (!apiobj)  {
-        Py_DECREF (pygame_register_quit);
         DECREF_MOD(module);
         MODINIT_ERROR;
     }
 
     if (PyModule_AddObject(module, PYGAMEAPI_LOCAL_ENTRY, apiobj) == -1)  {
-        Py_DECREF(pygame_register_quit);
         Py_DECREF(apiobj);
         DECREF_MOD(module);
         MODINIT_ERROR;
     }
 
-    quit = PyObject_GetAttrString (module, "quit");
-    if (!quit) {  /* assertion */
-        Py_DECREF (pygame_register_quit);
-        DECREF_MOD (module);
-        MODINIT_ERROR;
-    }
-    rval = PyObject_CallFunctionObjArgs (pygame_register_quit, quit, 0);
-    Py_DECREF (pygame_register_quit);
-    Py_DECREF (quit);
-    if (!rval) {
-        DECREF_MOD (module);
-        MODINIT_ERROR;
-    }
-    Py_DECREF (rval);
-
     MODINIT_RETURN(module);
 }

test/freetype_test.py

             if was_init:
                 ft.quit()
 
+    def test_autoinit_and_autoquit(self):
+        pygame.init()
+        self.assertTrue(ft.was_init())
+        pygame.quit()
+        self.assertFalse(ft.was_init())
+
+        # Ensure autoquit is replaced at init time
+        pygame.init()
+        self.assertTrue(ft.was_init())
+        pygame.quit()
+        self.assertFalse(ft.was_init())
 
 if __name__ == '__main__':
     unittest.main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.