Commits

Anonymous committed 63f9a19

Aliased/antialiased rendering on FT fonts.

Comments (0)

Files changed (5)

 * >8 bpp surfaces with palettes - it is supported (although it might be
   pointless) by SDL and so should we.
 
-* freetype: bgcolor needs to be respected on rendering to an existing surface.
 * freetype: bgcolor with alpha transparency needs to be respected on rendering
-* freetype: width and height's not exactly correct (box extents are not
-  fitted to the visible character)
-* freetype: rotated text rendering and proper support for vertical fonts
 * freetype: render to buffer buffer support (like new bytearray, but
   write to a buffer instead)
 * freetype: support different rendering modes (antialiased, aliased, ...)?

examples/freetype/sdlfont.py

     screen.fill (pygame2.Color (200, 200, 200))
     w, h, _ = font.render("Hello", pygame2.Color(100, 100, 100), None, screen, 100, 100, ptsize=48)
 
-    w, h, _ = font.render("World", pygame2.Color(200, 100, 100), pygame2.Color(255, 0xCC, 0), screen, 100, 200, ptsize=48, vertical = True, rotation = 45)
+    w, h, _ = font.render("World", pygame2.Color(200, 100, 100), pygame2.Color(255, 0xCC, 0), screen, 100, 200, ptsize=48, vertical = True, rotation = 45, antialias = False)
 
 #    w, g, buf = font.render("Hello World, Jay",
 #            pygame2.Color(100, 200, 32),

src/freetype/ft_font.c

                 &text, &vertical_obj, &rotation, &ptsize))
         return NULL;
 
-    if (ptsize == -1)
-    {
-        if (font->default_ptsize == -1)
-        {
-            PyErr_SetString(PyExc_ValueError,
-                    "Missing font size argument and no default size specified");
-            return NULL;
-        }
-        
-        ptsize = font->default_ptsize;
-    }
-
-    if (vertical_obj && PyObject_IsTrue(vertical_obj))
-        vertical = 1;
+    PGFT_CHECK_PTSIZE();
+    PGFT_CHECK_BOOL(vertical_obj, vertical);
 
     PGFT_BuildRenderMode(&render, vertical, FONT_RENDER_ANTIALIAS, rotation);
 
         return NULL;
 
     /* check ptsize */
-    if (ptsize == -1)
-    {
-        if (font->default_ptsize == -1)
-        {
-            PyErr_SetString(PyExc_ValueError,
-                    "Missing font size argument and no default size specified");
-            return NULL;
-        }
-        
-        ptsize = font->default_ptsize;
-    }
+    PGFT_CHECK_PTSIZE();
 
     /* check text */
     if (PyUnicode_Check(text))
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &text, &ptsize))
         return NULL;
 
-    if (ptsize == -1)
-    {
-        if (font->default_ptsize == -1)
-        {
-            PyErr_SetString(PyExc_ValueError,
-                    "Missing font size argument and no default size specified");
-            return NULL;
-        }
-        
-        ptsize = font->default_ptsize;
-    }
+    PGFT_CHECK_PTSIZE();
 
     rbuffer = PGFT_Render_PixelArray(ft, font, ptsize, text, &width, &height);
 
     static char *kwlist[] = 
     { 
         "text", "fgcolor", "bgcolor", "dstsurface", 
-        "xpos", "ypos", "vertical", "rotation", "ptsize", NULL
+        "xpos", "ypos", "vertical", "rotation", "antialias", "ptsize", NULL
     };
 
     PyFreeTypeFont *font = (PyFreeTypeFont *)self;
     PyObject *fg_color = NULL;
     PyObject *bg_color = NULL;
     PyObject *vertical_obj = NULL;
+    PyObject *antialias_obj = NULL;
     int rotation = 0;
     int xpos = 0, ypos = 0;
 
 
     FontRenderMode render;
     int vertical = 0;
+    int antialias = 1;
 
     FreeTypeInstance *ft;
     ASSERT_GRAB_FREETYPE(ft, NULL);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiiOii", kwlist,
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiiOiOi", kwlist,
                 &text, &fg_color, &bg_color, &target_surf, &xpos, &ypos, 
-                &vertical_obj, &rotation, &ptsize))
+                &vertical_obj, &rotation, &antialias_obj, &ptsize))
         return NULL;
 
-    if (ptsize == -1)
-    {
-        if (font->default_ptsize == -1)
-        {
-            PyErr_SetString(PyExc_ValueError,
-                    "Missing font size argument and no default size specified");
-            return NULL;
-        }
-        
-        ptsize = font->default_ptsize;
-    }
+    PGFT_CHECK_PTSIZE();
 
     if (!PyColor_Check(fg_color))
     {
         }
     }
 
-    if (vertical_obj && PyObject_IsTrue(vertical_obj))
-        vertical = 1;
+    PGFT_CHECK_BOOL(vertical_obj, vertical);
+    PGFT_CHECK_BOOL(antialias_obj, antialias);
 
     /* TODO: handle antialiasing */
-    PGFT_BuildRenderMode(&render, vertical, FONT_RENDER_ANTIALIAS, rotation);
-
+    PGFT_BuildRenderMode(&render, vertical, antialias, rotation);
 
     if (!target_surf || target_surf == Py_None)
     {

src/freetype/ft_render.c

 typedef void (* FontRenderPtr)(int, int, FontSurface *, FT_Bitmap *, PyColor *);
 
 /* blitters */
+void __render_glyph_MONO1(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
+void __render_glyph_MONO2(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
+void __render_glyph_MONO4(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
+
 void __render_glyph_SDL8(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
 void __render_glyph_SDL16(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
 void __render_glyph_SDL24(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
 void __render_glyph_SDL32(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
+
 void __render_glyph_ByteArray(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, PyColor *color);
 
 void 
     }                                                           
 } 
 
+#define _CREATE_MONO_RENDER(_bpp, T)                                    \
+    void __render_glyph_MONO##_bpp(int rx, int ry, FontSurface *surface,\
+            FT_Bitmap *bitmap, PyColor *color)                          \
+    {                                                                   \
+        int             x, y;                                           \
+        unsigned char*  src;                                            \
+        unsigned char*  dst;                                            \
+        FT_UInt32       tcolor;                                         \
+                                                                        \
+        src  = bitmap->buffer;                                          \
+        dst = (unsigned char *)surface->buffer + (rx * _bpp) +          \
+                    (ry * _bpp * surface->pitch);                       \
+                                                                        \
+        tcolor = (T)SDL_MapRGB(surface->format,                         \
+            (FT_Byte)color->r, (FT_Byte)color->g, (FT_Byte)color->b);   \
+                                                                        \
+        y = bitmap->rows;                                               \
+        do                                                              \
+        {                                                               \
+            unsigned char*  _src = src;                                 \
+            unsigned char*  _dst = dst;                                 \
+            FT_UInt32       val = (FT_UInt32)(*_src++ | 0x100);         \
+                                                                        \
+            x = bitmap->width;                                          \
+            do                                                          \
+            {                                                           \
+                if (val & 0x10000)                                      \
+                    val = (FT_UInt32)(*_src++ | 0x100);                 \
+                                                                        \
+                if (val & 0x80)                                         \
+                    *(T *)_dst = (T)tcolor;                             \
+                                                                        \
+                val   <<= 1;                                            \
+                _dst += _bpp;                                           \
+            } while (--x > 0);                                          \
+                                                                        \
+            src  += bitmap->pitch;                                      \
+            dst += surface->pitch * _bpp;                               \
+        } while (--y > 0);                                              \
+    }
+
 #define _CREATE_SDL_RENDER(bpp, T, _build_pixel)                    \
     void __render_glyph_SDL##bpp(int rx, int ry, FontSurface *surface,\
         FT_Bitmap *bitmap, PyColor *color)                          \
 _CREATE_SDL_RENDER(16,  FT_UInt16,  BUILD_PIXEL_TRUECOLOR)
 _CREATE_SDL_RENDER(8,   FT_Byte,    BUILD_PIXEL_GENERIC)
 
+_CREATE_MONO_RENDER(4,  FT_UInt32)
+_CREATE_MONO_RENDER(2,  FT_UInt16)
+_CREATE_MONO_RENDER(1,   FT_Byte)
+
 int PGFT_Render_ExistingSurface(FreeTypeInstance *ft, PyFreeTypeFont *font,
     int font_size, FontRenderMode *render, PyObject *text, PySDLSurface *_surface, 
     int x, int y, PyColor *fgcolor, PyColor *bgcolor, int *_width, int *_height)
 {
-    static const FontRenderPtr __renderFuncs[] =
+    static const FontRenderPtr __SDLrenderFuncs[] =
     {
         NULL,
         __render_glyph_SDL8,
         __render_glyph_SDL32
     };
 
+    static const FontRenderPtr __MONOrenderFuncs[] =
+    {
+        NULL,
+        __render_glyph_MONO1,
+        __render_glyph_MONO2,
+        NULL,
+        __render_glyph_MONO4,
+    };
+
     int         locked = 0;
 
     SDL_Surface *surface;
     font_surf.pitch = surface->pitch / surface->format->BytesPerPixel;
 
     font_surf.format = surface->format;
-    font_surf.render = __renderFuncs[surface->format->BytesPerPixel];
+
+    if (render->antialias == FONT_RENDER_ANTIALIAS)
+    {
+        font_surf.render = __SDLrenderFuncs[surface->format->BytesPerPixel];
+    }
+    else
+    {
+        font_surf.render = __MONOrenderFuncs[surface->format->BytesPerPixel];
+    }
 
     /*
      * Render!

src/freetype/ft_wrap.h

 #define PGFT_ROUND(x)  ( ( (x) + 32 ) & -64 )
 #define PGFT_TRUNC(x)  (   (x) >> 6 )
 
+
+#define PGFT_CHECK_PTSIZE()                             \
+    if (ptsize == -1)                                   \
+    {                                                   \
+        if (font->default_ptsize == -1)                 \
+        {                                               \
+            PyErr_SetString(PyExc_ValueError,           \
+                    "Missing font size argument "       \
+                    "and no default size specified");   \
+            return NULL;                                \
+        }                                               \
+                                                        \
+        ptsize = font->default_ptsize;                  \
+    }
+
+#define PGFT_CHECK_BOOL(_pyobj, _var)               \
+    if (_pyobj)                                     \
+    {                                               \
+        if (!PyBool_Check(_pyobj))                  \
+        {                                           \
+            PyErr_SetString(PyExc_TypeError,        \
+                #_var " must be a boolean value");  \
+            return NULL;                            \
+        }                                           \
+                                                    \
+        _var = PyObject_IsTrue(_pyobj);             \
+    }
+
 #define UNICODE_BOM_NATIVE	0xFEFF
 #define UNICODE_BOM_SWAPPED	0xFFFE