Commits

tanoku  committed 127e1e2

Font loading in FreeType module using SDL RWops (WIP)

  • Participants
  • Parent commits d351325
  • Branches pgreloaded

Comments (0)

Files changed (5)

     Module ("freetype.base",
         sources = [
             "src/freetype/ft_mod.c",
-            "src/freetype/ft_font.c"
-            ],
+            "src/freetype/ft_font.c",
+            "src/freetype/ft_wrap.c"
+        ],
         instheaders = ["src/freetype/pgfreetype.h"],
         docfile = "freetypebase.xml",
         depends = ['freetype', 'SDL']),

File src/freetype/ft_font.c

 static void
 _ftfont_dealloc(PyFreeTypeFont *self)
 {
-    /* TODO */
+    FreeTypeInstance *ft;
+
+    if ((ft = _get_freetype()) != NULL)
+        PGFT_UnloadFont(ft, self);
+
+    ((PyObject*)self)->ob_type->tp_free((PyObject *)self);
 }
 
 static PyObject*
 _ftfont_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    /* TODO */
+    PyFreeTypeFont *font = (PyFreeTypeFont*)type->tp_alloc(type, 0);
+
+    if (!font)
+        return NULL;
+
+    font->rwops = NULL;
+
+    font->pyfont.get_height = _ftfont_getheight;
+    font->pyfont.get_name = _ftfont_getname;
+    font->pyfont.get_style = _ftfont_getstyle;
+    font->pyfont.set_style = _ftfont_setstyle;
+    font->pyfont.get_size = _ftfont_getsize;
+    font->pyfont.render = _ftfont_render;
+    font->pyfont.copy = NULL; /* TODO */
+
+    return (PyObject*)font;
 }
 
 static int
 _ftfont_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    /* TODO */
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+    
+    PyObject *file;
+    int face_index = 0;
+
+    FreeTypeInstance *ft;
+    ASSERT_GRAB_FREETYPE(ft, -1);
+
+    if (!PyArg_ParseTuple(args, "O|i", &file, &face_index))
+        return -1;
+
+    if (face_index < 0)
+    {
+        PyErr_SetString(PyExc_ValueError, "Face index cannot be negative");
+        return -1;
+    }
+
+    font->face_index = face_index;
+    font->rwops = PyRWops_NewRO_Threaded(file, &font->autoclose);
+    if (!font->rwops)
+        return -1;
+
+    /*
+     * TODO: Do we have to close it later if autoclose
+     * it 1 or will SLD_RWops handle it?
+     */
+    if (!font->autoclose)
+        PyRWops_Close(font->rwops, font->autoclose);
+
+    if (!font)
+    {
+        PyErr_SetString(PyExc_PyGameError, PGFT_GetError());
+        return -1;
+    }
+
+    return 0;
 }
 
 

File src/freetype/ft_mod.c

 #include "pgsdl.h"
 #include "freetypebase_doc.h"
 
-static FT_Library g_freetype_lib = NULL;
+static FreeTypeInstance *__freetype = NULL;
 
 static int _init(void);
 static void _quit(void);
  * libraries based on the active thread to prevent multi-
  * threading issues.
  */
-static FT_Library
+FreeTypeInstance *
 _get_freetype(void)
 {
-    return g_freetype_lib;
+    return __freetype;
 }
 
 /*
 static void
 _quit(void)
 {
-    if (g_freetype_lib)
+    if (__freetype)
     {
-        FT_Done_FreeType(g_freetype_lib);
-        g_freetype_lib = NULL;
+        PGFT_Quit(__freetype);
+        __freetype = NULL;
     }
 }
 
 /*
  * Initialize the FreeType library.
- * Return 1 if initialization was successful, 0 otherwise.
  */
 static int
 _init(void)
 {
     FT_Error error;
 
-    if (g_freetype_lib)
-        return 1;
+    if (__freetype)
+        return 0;
 
-    error = FT_Init_FreeType(&g_freetype_lib);
+    error = PGFT_Init(&__freetype);
 
-    return (error == 0);
+    return (error);
 }
 
 /***************************************************************
 static PyObject *
 _ft_init(PyObject *self)
 {
-    if (g_freetype_lib)
-        Py_RETURN_NONE;
-    
-    if (_init() == 0)
+    if (_init() != 0)
     {
         /* TODO: More accurate error message */
         PyErr_SetString(PyExc_PyGameError, 
 static PyObject *
 _ft_was_init(PyObject *self)
 {
-    return PyBool_FromLong((g_freetype_lib != 0));
+    return PyBool_FromLong((__freetype != 0));
 }
 
 PyMODINIT_FUNC

File src/freetype/ft_wrap.c

+/*
+  pygame - Python Game Library
+  Copyright (C) 2000-2001 Pete Shinners
+  Copyright (C) 2008 Marcus von Appen
+  Copyright (C) 2009 Vicent Marti
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Library General Public
+  License as published by the Free Software Foundation; either
+  version 2 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Library General Public License for more details.
+
+  You should have received a copy of the GNU Library General Public
+  License along with this library; if not, write to the Free
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#define PYGAME_FREETYPE_INTERNAL
+
+#include "ft_mod.h"
+#include "pgfreetype.h"
+#include "pgsdl.h"
+#include "freetypebase_doc.h"
+
+void    PGFT_Quit(FreeTypeInstance *);
+int     PGFT_Init(FreeTypeInstance **);
+int     PGFT_TryLoadFont(FreeTypeInstance *ft, PyFreeTypeFont *font);
+void    PGFT_UnloadFont(FreeTypeInstance *, PyFreeTypeFont *);
+
+void    _PGTF_SetError(const char *error_msg, FT_Error error_id);
+
+
+
+static unsigned long 
+_RWread(FT_Stream stream, 
+        unsigned long offset, 
+        unsigned char* buffer, 
+        unsigned long count)
+{
+	SDL_RWops *src;
+
+	src = (SDL_RWops *)stream->descriptor.pointer;
+	SDL_RWseek(src, (int)offset, SEEK_SET);
+
+	if (count == 0)
+		return 0;
+
+	return SDL_RWread(src, buffer, 1, (int)count);
+}
+
+
+
+static FT_Error
+_PGTF_face_request(FTC_FaceID face_id, 
+        FT_Library library, 
+        FT_Pointer request_data, 
+        FT_Face *aface)
+{
+    PyFreeTypeFont *font = (PyFreeTypeFont *)face_id;
+
+    FT_Error error = 0;
+    FT_Stream stream = NULL;
+    int position;
+    
+	position = SDL_RWtell(font->rwops);
+
+	if (position < 0)
+        goto error_cleanup;
+
+    stream = malloc(sizeof(FT_Stream));
+
+	if (stream == NULL) 
+        goto error_cleanup;
+
+	memset(stream, 0, sizeof(FT_Stream));
+
+	stream->read = _RWread;
+	stream->descriptor.pointer = font->rwops;
+	stream->pos = (unsigned long)position;
+	SDL_RWseek(font->rwops, 0, SEEK_END);
+	stream->size = (unsigned long)(SDL_RWtell(font->rwops) - position);
+	SDL_RWseek(font->rwops, position, SEEK_SET);
+
+	font->open_args.flags = FT_OPEN_STREAM;
+	font->open_args.stream = stream;
+
+	error = FT_Open_Face(library, &font->open_args, font->face_index, aface);
+
+    if (error)
+        goto error_cleanup;
+
+    return 0;
+
+error_cleanup:
+    free(stream);
+    return error ? error : -1;
+}
+
+void
+_PGTF_SetError(const char *error_msg, FT_Error error_id)
+{
+
+}
+
+int
+PGFT_TryLoadFont(FreeTypeInstance *ft, PyFreeTypeFont *font)
+{
+    FT_Face face;
+    FT_Error error;
+
+    error = FTC_Manager_LookupFace(ft->cache_manager, (FTC_FaceID)font, &face);
+
+    if (error)
+    {
+        _PGTF_SetError("Failed to load font", error);
+        return error;
+    }
+
+    return 0;
+}
+
+void
+PGFT_UnloadFont(FreeTypeInstance *ft, PyFreeTypeFont *font)
+{
+    FTC_Manager_RemoveFaceID(ft->cache_manager, (FTC_FaceID)font);
+}
+
+void
+PGFT_Quit(FreeTypeInstance *ft)
+{
+    if (ft == NULL)
+        return;
+
+    /* TODO: Free caches */
+
+    FTC_Manager_Done(ft->cache_manager);
+    FT_Done_FreeType(ft->library);
+    free(ft);
+}
+
+int
+PGFT_Init(FreeTypeInstance **_instance)
+{
+    FT_Error error = 0;
+    FreeTypeInstance *inst = NULL;
+
+    inst = malloc(sizeof(FreeTypeInstance));
+
+    if (!inst)
+        goto error_cleanup;
+    
+    error = FT_Init_FreeType(&inst->library);
+
+    if (error)
+        goto error_cleanup;
+
+    error = FTC_Manager_New(
+            inst->library, 
+            0, 0, 0, 
+            &_PGTF_face_request, 
+            NULL, 
+            &inst->cache_manager);
+
+    if (error)
+        goto error_cleanup;
+
+    return 0;
+
+error_cleanup:
+    free(inst);
+    *_instance = NULL;
+
+    return error;
+}

File src/freetype/pgfreetype.h

 #ifndef _PYGAME_FONTS_H_
 #define _PYGAME_FONTS_H_
 
+#include <SDL.h>
 #include "pgbase.h"
 
 #include <ft2build.h>  
 #include FT_FREETYPE_H 
+#include FT_CACHE_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-static FT_Library _get_freetype(void);
+typedef struct
+{
+    FT_Library library;
+    FTC_Manager cache_manager;
+    FTC_SBitCache cache_bitmap;
+    FTC_CMapCache cache_charmap;
+} FreeTypeInstance;
 
-#define ASSERT_FREETYPE_INIT(x)                                 \
-    if (_get_freetype() == NULL)                                \
+FreeTypeInstance *_get_freetype(void);
+
+#define ASSERT_GRAB_FREETYPE(ft_ptr, rvalue)                    \
+    ft_ptr = _get_freetype();                                   \
+    if (ft_ptr == NULL)                                         \
     {                                                           \
         PyErr_SetString(PyExc_PyGameError,                      \
             "The FreeType 2 library hasn't been initialized");  \
-        return (x);                                             \
+        return (rvalue);                                        \
     }
 
 #define PYGAME_FREETYPE_FIRSTSLOT 0
 typedef struct
 {
     PyFont pyfont;
-    
-    /*
-     * TODO: Add pointer to our FT font!
-     *
-     * FT_Face *font;
-     */
 
+    int face_index;
+    SDL_RWops *rwops;
+    int autoclose;
+    FT_Open_Args open_args;
 } PyFreeTypeFont;
 
 #define PyFreeTypeFont_AsFont(x) (((PyFreeTypeFont *)x)->font)