Commits

Anonymous committed 2063280

Backported API changes.
Added FreeType example to examples folder.

Comments (0)

Files changed (8)

examples/freetype_misc.py

+import sys, os
+import pygame
+from pygame.locals import *
+
+try:
+    import pygame.freetype as freetype
+except ImportError:
+    print ("No FreeType support compiled")
+    sys.exit ()
+
+colors = {
+    "grey_light"    :   pygame.Color(200, 200, 200),
+    "grey_dark"     :   pygame.Color(100, 100, 100),
+    "green"         :   pygame.Color(50, 255, 63),
+    "red"           :   pygame.Color(220, 30, 30),
+    "blue"          :   pygame.Color(50, 75, 245)
+}
+
+def run():
+    pygame.init()
+    freetype.init()
+
+    fontdir = os.path.dirname(os.path.abspath (__file__))
+    font = freetype.Font(os.path.join (fontdir, "sans.ttf"))
+
+    screen = pygame.display.set_mode((800, 600))
+    screen.fill (colors["grey_light"])
+
+    font.render((screen, 32, 32), "Hello World", colors["red"], colors['grey_dark'],
+            ptsize=64, style=freetype.STYLE_UNDERLINE|freetype.STYLE_ITALIC)
+
+    font.render((screen, 32, 128), "abcdefghijklm", colors["grey_dark"], colors["green"],
+            ptsize=64)
+
+    font.vertical = True
+    font.render((screen, 32, 190), "Vertical?", colors["blue"], None, ptsize=32)
+    font.vertical = False
+
+    font.render((screen, 64, 190), "Let's spin!", colors["red"], None,
+            ptsize=48, rotation=55)
+
+    font.render((screen, 150, 270), "All around!", colors["green"], None,
+            ptsize=48, rotation=-55)
+
+    font.render((screen, 250, 220), "and BLEND", pygame.Color(255, 0, 0, 128), None,
+            ptsize=64)
+
+    font.render((screen, 258, 237), "or BLAND!", pygame.Color(0, 0xCC, 28, 128), None,
+            ptsize=64)
+
+    font.render((screen, 298, 320), "I \u2665 Unicode", pygame.Color(0, 0xCC, 0xDD), None,
+            ptsize=64)
+
+    font.render((screen, 480, 32), "\u2665", colors["grey_light"], colors["red"],
+            ptsize=148)
+
+    font.render((screen, 380, 380), "...yes, this is a SDL surface", pygame.Color(0, 0, 0), None,
+            ptsize=24, style=freetype.STYLE_BOLD)
+
+    pygame.display.flip()
+
+    while 1:
+        if pygame.event.wait().type in (QUIT, KEYDOWN, MOUSEBUTTONDOWN):
+            break
+
+    pygame.quit()
+
+if __name__ == "__main__":
+    run ()

Binary file added.

src/freetype/freetype.c

 static PyObject* _ftfont_getname(PyObject *self, void *closure);
 static PyObject* _ftfont_getfixedwidth(PyObject *self, void *closure);
 
+static PyObject* _ftfont_getvertical(PyObject *self, void *closure);
+static int _ftfont_setvertical(PyObject *self, PyObject *value, void *closure);
+static PyObject* _ftfont_getantialias(PyObject *self, void *closure);
+static int _ftfont_setantialias(PyObject *self, PyObject *value, void *closure);
+
+static PyObject* _ftfont_getstyle_flag(PyObject *self, void *closure);
+static int _ftfont_setstyle_flag(PyObject *self, PyObject *value, void *closure);
+
 /*
  * FREETYPE MODULE METHODS TABLE
  */
         "TODO",
         NULL
     },
+    {
+        "antialiased",
+        _ftfont_getantialias,
+        _ftfont_setantialias,
+        "TODO",
+        NULL
+    },
+    {
+        "vertical",
+        _ftfont_getvertical,
+        _ftfont_setvertical,
+        "TODO",
+        NULL
+    },
+    {
+        "italic",
+        _ftfont_getstyle_flag,
+        _ftfont_setstyle_flag,
+        "TODO", /* TODO: Doc */
+        (void *)FT_STYLE_ITALIC
+    },
+    {
+        "bold",
+        _ftfont_getstyle_flag,
+        _ftfont_setstyle_flag,
+        "TODO", /* TODO: Doc */
+        (void *)FT_STYLE_BOLD
+    },
+    {
+        "underline",
+        _ftfont_getstyle_flag,
+        _ftfont_setstyle_flag,
+        "TODO", /* TODO: Doc */
+        (void *)FT_STYLE_UNDERLINE
+    },
     { NULL, NULL, NULL, NULL, NULL }
 };
 
         PyErr_SetString(PyExc_ValueError, "Face index cannot be negative");
         goto end;
     }
+    
+    /* TODO: Check style? Ask for vertical? */
 
-    font->default_ptsize = (ptsize <= 0) ? -1 : ptsize;
-    font->default_style = font_style;
+    font->ptsize = (FT_Int16)((ptsize <= 0) ? -1 : ptsize);
+    font->style = (FT_Byte)font_style;
+    font->antialias = 1;
+    font->vertical = 0;
 
     if (file == Py_None)
     {
 /****************************************************
  * GETTERS/SETTERS
  ****************************************************/
+
+/** Vertical attribute */
+static PyObject*
+_ftfont_getvertical(PyObject *self, void *closure)
+{
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+    return PyBool_FromLong(font->vertical);
+}
+
+static int
+_ftfont_setvertical(PyObject *self, PyObject *value, void *closure)
+{
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+    if (!PyBool_Check(value))
+    {
+        PyErr_SetString(PyExc_TypeError, "Expecting 'bool' type");
+        return -1;
+    }
+    font->vertical = (FT_Byte)PyObject_IsTrue(value);
+    return 0;
+}
+
+
+/** Antialias attribute */
+static PyObject*
+_ftfont_getantialias(PyObject *self, void *closure)
+{
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+    return PyBool_FromLong(font->antialias);
+}
+
+static int
+_ftfont_setantialias(PyObject *self, PyObject *value, void *closure)
+{
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+    if (!PyBool_Check(value))
+    {
+        PyErr_SetString(PyExc_TypeError, "Expecting 'bool' type");
+        return -1;
+    }
+    font->antialias = (FT_Byte)PyObject_IsTrue(value);
+    return 0;
+}
+
+
+/** Generic style attributes */
+static PyObject*
+_ftfont_getstyle_flag(PyObject *self, void *closure)
+{
+    const int style_flag = (int)closure;
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+
+    return PyBool_FromLong(font->style & style_flag);
+}
+
+static int
+_ftfont_setstyle_flag(PyObject *self, PyObject *value, void *closure)
+{
+    const int style_flag = (int)closure;
+    PyFreeTypeFont *font = (PyFreeTypeFont *)self;
+
+    if (!PyBool_Check(value))
+    {
+        PyErr_SetString(PyExc_TypeError,
+                "The style value must be a boolean");
+        return -1;
+    }
+
+    if (PyObject_IsTrue(value))
+    {
+        font->style |= (FT_Byte)style_flag;
+    }
+    else
+    {
+        font->style &= (FT_Byte)(~style_flag);
+    }
+
+    return 0;
+}
+
+
+/** Style attribute */
 static PyObject*
 _ftfont_getstyle (PyObject *self, void *closure)
 {
     PyFreeTypeFont *font = (PyFreeTypeFont *)self;
 
-    return PyInt_FromLong(font->default_style);
+    return PyInt_FromLong(font->style);
 }
 
 static int
         return -1;
     }
 
-    font->default_style = style;
+    font->style = (FT_Byte)style;
     return 0;
 }
 
     /* keyword list */
     static char *kwlist[] = 
     { 
-        "text", "style", "vertical", "rotation", "ptsize", NULL
+        "text", "style", "rotation", "ptsize", NULL
     };
 
     PyFreeTypeFont *font = (PyFreeTypeFont *)self;
     int width, height;
 
     FontRenderMode render;
-    int vertical = 0;
     int rotation = 0;
     int style = 0;
 
-    PyObject *vertical_obj = NULL;
-
     FreeTypeInstance *ft;
     ASSERT_GRAB_FREETYPE(ft, NULL);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iOii", kwlist, 
-                &text, &style, &vertical_obj, &rotation, &ptsize))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, 
+                &text, &style, &rotation, &ptsize))
         return NULL;
 
-    PGFT_CHECK_BOOL(vertical_obj, vertical);
-
     /* Build rendering mode, always anti-aliased by default */
-    if (PGFT_BuildRenderMode(ft, font, 
-            &render, ptsize, style, vertical, 1, rotation) != 0)
+    if (PGFT_BuildRenderMode(ft, font, &render, 
+                ptsize, style, rotation) != 0)
     {
-        PyErr_SetString(PyExc_RuntimeError, PGFT_GetError(ft));
+        PyErr_SetString(PyExc_ValueError, PGFT_GetError(ft));
         return NULL;
     }
 
      * rotation/styles/vertical text
      */
     if (PGFT_BuildRenderMode(ft, font, 
-                &render, ptsize, FT_STYLE_NORMAL, 0, 1, 0) != 0)
+                &render, ptsize, FT_STYLE_NORMAL, 0) != 0)
     {
-        PyErr_SetString(PyExc_RuntimeError, PGFT_GetError(ft));
+        PyErr_SetString(PyExc_ValueError, PGFT_GetError(ft));
         return NULL;
     }
 
      * rotation/styles/vertical text
      */
     if (PGFT_BuildRenderMode(ft, font, 
-                &render, ptsize, FT_STYLE_NORMAL, 0, 1, 0) != 0)
+                &render, ptsize, FT_STYLE_NORMAL, 0) != 0)
     {
-        PyErr_SetString(PyExc_RuntimeError, PGFT_GetError(ft));
+        PyErr_SetString(PyExc_ValueError, PGFT_GetError(ft));
         return NULL;
     }
 
     /* keyword list */
     static char *kwlist[] = 
     { 
-        "text", "fgcolor", "bgcolor", "dstsurface", 
-        "xpos", "ypos", "style", "vertical", "rotation", "antialias", "ptsize", NULL
+        "dest", "text", "fgcolor", "bgcolor", 
+        "style", "rotation", "ptsize", NULL
     };
 
     PyFreeTypeFont *font = (PyFreeTypeFont *)self;
     /* input arguments */
     PyObject *text = NULL;
     int ptsize = -1;
-    PyObject *target_surf = NULL;
+    PyObject *target_tuple = NULL;
     PyObject *fg_color_obj = NULL;
     PyObject *bg_color_obj = NULL;
-    PyObject *vertical_obj = NULL;
-    PyObject *antialias_obj = NULL;
     int rotation = 0;
-    int xpos = 0, ypos = 0;
     int style = FT_STYLE_DEFAULT;
 
     /* output arguments */
 
     FontColor fg_color, bg_color;
     FontRenderMode render;
-    int vertical = 0;
-    int antialias = 1;
 
     FreeTypeInstance *ft;
     ASSERT_GRAB_FREETYPE(ft, NULL);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiiiOiOi", kwlist,
-                &text, &fg_color_obj, &bg_color_obj, &target_surf, &xpos, &ypos, 
-                &style, &vertical_obj, &rotation, &antialias_obj, &ptsize))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|Oiii", kwlist,
+                &target_tuple, &text, &fg_color_obj, /* required */
+                &bg_color_obj, &style, &rotation, &ptsize)) /* optional */
         return NULL;
 
     if (!RGBAFromColorObj(fg_color_obj, (Uint8 *)&fg_color))
         }
     }
 
-    PGFT_CHECK_BOOL(vertical_obj, vertical);
-    PGFT_CHECK_BOOL(antialias_obj, antialias);
-
     if (PGFT_BuildRenderMode(ft, font, 
-                &render, ptsize, style, vertical, antialias, rotation) != 0)
+                &render, ptsize, style, rotation) != 0)
     {
-        PyErr_SetString(PyExc_RuntimeError, PGFT_GetError(ft));
+        PyErr_SetString(PyExc_ValueError, PGFT_GetError(ft));
         return NULL;
     }
 
-    if (!target_surf || target_surf == Py_None)
+    if (target_tuple == Py_None)
     {
         SDL_Surface *r_surface = NULL;
 
             return NULL;
         }
 
-        rtuple = Py_BuildValue("(iiO)", width, height, 
-                PySurface_New(r_surface));
+        rtuple = Py_BuildValue("(Oii)", 
+                PySurface_New(r_surface), width, height);
+               
     }
-    else if (PySurface_Check(target_surf))
+    else
     {
         SDL_Surface *surface = NULL;
-        surface = PySurface_AsSurface(target_surf);
+        PyObject *surface_obj = NULL;
+        int xpos = 0, ypos = 0;
+
+        if (!PyArg_ParseTuple(target_tuple, "Oii", &surface_obj, &xpos, &ypos))
+            return NULL;
+
+        if (!PySurface_Check(surface_obj))
+        {
+            PyErr_SetString(PyExc_TypeError, "Target surface must be a SDL surface");
+            return NULL;
+        }
+
+        surface = PySurface_AsSurface(surface_obj);
 
         if (PGFT_Render_ExistingSurface(ft, font, &render, 
                 text, surface, xpos, ypos, 
             return NULL;
         }
 
-        Py_INCREF(target_surf); 
-        rtuple = Py_BuildValue("(iiO)", width, height, target_surf);
-    }
-    else
-    {
-        PyErr_SetString(PyExc_TypeError, 
-                "The given target is not a valid SDL surface");
-        return NULL;
+        rtuple = Py_BuildValue("(iiO)", width, height);
     }
 
     return rtuple;
     if (!font)
         return NULL;
 
-    font->default_ptsize = -1;
-    font->default_style = FT_STYLE_NORMAL;
+    font->ptsize = -1;
+    font->style = FT_STYLE_NORMAL;
+    font->antialias = 1;
+    font->vertical = 0;
 
     if (PGFT_TryLoadFont_Filename(ft, font, filename, face_index) != 0)
     {

src/freetype/ft_render.c

 int 
 PGFT_BuildRenderMode(FreeTypeInstance *ft, 
         PyFreeTypeFont *font, FontRenderMode *mode, 
-        int pt_size, int style, int vertical, int antialias, int rotation)
+        int pt_size, int style, int rotation)
 {
     int angle;
 
     if (pt_size == -1)
     {
-        if (font->default_ptsize == -1)
+        if (font->ptsize == -1)
         {
             _PGFT_SetError(ft, "No font point size specified"
                     " and no default font size in typeface", 0);
             return -1;
         }
 
-        pt_size = font->default_ptsize;
+        pt_size = font->ptsize;
     }
 
     if (pt_size <= 0)
 
     if (style == FT_STYLE_DEFAULT)
     {
-        mode->style = (FT_Byte)font->default_style;
+        mode->style = (FT_Byte)font->style;
     }
     else
     {
 
     mode->render_flags = FT_RFLAG_DEFAULTS;
 
-    if (vertical)
+    if (font->vertical)
         mode->render_flags |= FT_RFLAG_VERTICAL;
 
-    if (antialias)
+    if (font->antialias)
         mode->render_flags |= FT_RFLAG_ANTIALIAS;
 
     angle = rotation % 360;

src/freetype/ft_wrap.c

         }
     }
 
-    if (ft_msg)
+    if (error_id && ft_msg)
         sprintf(ft->_error_msg, "%s: %s", error_msg, ft_msg);
     else
         strcpy(ft->_error_msg, error_msg);

src/freetype/ft_wrap.h

 
 int         PGFT_BuildRenderMode(FreeTypeInstance *ft, 
                 PyFreeTypeFont *font, FontRenderMode *mode, int pt_size, 
-                int style, int vertical, int antialias, int rotation);
+                int style, int rotation);
 
 FT_Fixed    PGFT_GetBoldStrength(FT_Face face);
 

src/freetype/pgfreetype.h

     PyObject_HEAD
     FontId id;
 
-    int default_ptsize;
-    int default_style;
+    FT_Int16 ptsize;
+    FT_Byte style;
+    FT_Byte vertical;
+    FT_Byte antialias;
 
     void *_internals;
 } PyFreeTypeFont;

test/freetype_font_test.py

         test_size(size_bolden)
         self.assertTrue(size_bolden > size_default)
 
-        size_vert = font.get_size("ABCDabcd", ptsize=24, vertical=True)
+        font.vertical = True
+        size_vert = font.get_size("ABCDabcd", ptsize=24)
         test_size(size_vert)
         self.assertTrue(size_vert[0] < size_vert[1])
+        font.vertical = False
 
         size_italic = font.get_size("ABCDabcd", ptsize=24, style=ft.STYLE_ITALIC)
         test_size(size_italic)
         color = pygame.Color(0, 0, 0)
 
         # make sure we always have a valid fg color
-        self.assertRaises(TypeError, font.render, 'FoobarBaz')
-        self.assertRaises(TypeError, font.render, 'FoobarBaz', None)
+        self.assertRaises(TypeError, font.render, None, 'FoobarBaz')
+        self.assertRaises(TypeError, font.render, None, 'FoobarBaz', None)
 
         # render to new surface
-        rend = font.render('FoobarBaz', pygame.Color(0, 0, 0), None, None, ptsize=24)
+        rend = font.render(None, 'FoobarBaz', pygame.Color(0, 0, 0), None, ptsize=24)
+        self.assertTrue(isinstance(rend, tuple))
+        self.assertTrue(isinstance(rend[0], pygame.Surface))
+        self.assertTrue(isinstance(rend[1], int))
+        self.assertTrue(isinstance(rend[2], int))
+
+        # render to existing surface
+        rend = font.render((surf, 32, 32), 'FoobarBaz', color, None, ptsize=24)
         self.assertTrue(isinstance(rend, tuple))
         self.assertTrue(isinstance(rend[0], int))
         self.assertTrue(isinstance(rend[1], int))
-        self.assertTrue(isinstance(rend[2], pygame.Surface))
-
-        # render to existing surface
-        rend = font.render('FoobarBaz', color, None, surf, ptsize=24)
-        self.assertTrue(isinstance(rend, tuple))
-        self.assertTrue(isinstance(rend[0], int))
-        self.assertTrue(isinstance(rend[1], int))
-        self.assertTrue(isinstance(rend[2], pygame.Surface))
-        self.assertEqual(rend[2], surf)
 
         # misc parameter test
-        self.assertRaises(RuntimeError, font.render, 'foobar', color)
-        self.assertRaises(TypeError, font.render, 'foobar', color, "", ptsize=24)
-        self.assertRaises(TypeError, font.render, 'foobar', color,
-                None, 42, ptsize=24)
-        self.assertRaises(TypeError, font.render, 'foobar', color,
-                None, None, antialias=3, ptsize=24)
-        self.assertRaises(TypeError, font.render, 'foobar', color,
-                None, None, style=None, ptsize=24)
-        self.assertRaises(RuntimeError, font.render, 'foobar', color,
-                None, None, style=97, ptsize=24)
-
+        self.assertRaises(ValueError, font.render, None, 'foobar', color)
+        self.assertRaises(TypeError, font.render, None, 'foobar', color, "",
+                ptsize=24)
+        self.assertRaises(ValueError, font.render, None, 'foobar', color, None,
+                style=42, ptsize=24)
+        self.assertRaises(TypeError, font.render, None, 'foobar', color, None,
+                style=None, ptsize=24)
+        self.assertRaises(ValueError, font.render, None, 'foobar', color, None,
+                style=97, ptsize=24)
         pygame.quit()
 
 
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.