Commits

Lenard Lindstrom committed f49ac0c

freetype: attempted to get fancy with glyph rendering, but ended up undoing many of the changes. As a result the ft_render_cb.c macros are more involved, though there is less redundancy.

  • Participants
  • Parent commits 06cf89e

Comments (0)

Files changed (7)

File docs/reST/ref/freetype.rst

       Any sequence, including Rect, for which the first two elements are
       positions x and y is accepted.
 
-      If such a sequence exists, and the destination surface is a valid
-      :mod:`pygame.Surface` (independently of its bit depth), the text will be
-      rendered directly on top of it at the passed coordinates, using the given
-      'fgcolor', and painting the background of the text with the given
-      'bgcolor', if available. The alpha values for both colors are always
-      taken into account.
+      If a background color is given, the surface is first filled with that
+      color. The text is blitted next. Both the background fill and text
+      rendering involve full alpha blits. That is, the alpha values of
+      both the foreground and background colors, as well as those of the
+      destination surface if it has per-pixel alpha.
 
       The return value is a rectangle giving the size and position of the
       rendered text within the surface.
       If an empty string is passed for text then the returned Rect is zero
       width and the height of the face. The rect will test False.
 
-      The rendering is done using the face's default size in points and its
-      default style, without any rotation, and taking into account faces which
-      are set to be drawn vertically via the :meth:`Face.vertical` attribute.
-      Optionally you may specify another point size to use via the 'ptsize'
-      argument, a text rotation via the 'rotation' argument, or a new text
-      style via the 'style' argument.
+      By default, the point size and style set for the face are used
+      if not passed as arguments. The text is unrotated unless a non-zero
+      rotation value is given.
 
       If text is a char (byte) string, then its encoding is assumed to be
       ``LATIN1``.

File docs/ref/freetype.html

 or y is not an integer it is converted to one if possible.
 Any sequence, including Rect, for which the first two elements are
 positions x and y is accepted.</p>
-<p>If such a sequence exists, and the destination surface is a valid
-<a class="tooltip reference internal" href="surface.html#pygame.Surface" title=""><tt class="xref py py-mod docutils literal"><span class="pre">pygame.Surface</span></tt><span class="tooltip-content">pygame object for representing images</span></a> (independently of its bit depth), the text will be
-rendered directly on top of it at the passed coordinates, using the given
-&#8216;fgcolor&#8217;, and painting the background of the text with the given
-&#8216;bgcolor&#8217;, if available. The alpha values for both colors are always
-taken into account.</p>
+<p>If a background color is given, the surface is first filled with that
+color. The text is blitted next. Both the background fill and text
+rendering involve full alpha blits. That is, the alpha values of
+both the foreground and background colors, as well as those of the
+destination surface if it has per-pixel alpha.</p>
 <p>The return value is a rectangle giving the size and position of the
 rendered text within the surface.</p>
 <p>If an empty string is passed for text then the returned Rect is zero
 width and the height of the face. The rect will test False.</p>
-<p>The rendering is done using the face&#8217;s default size in points and its
-default style, without any rotation, and taking into account faces which
-are set to be drawn vertically via the <a class="reference internal" href="#pygame.freetype.Face.vertical" title="pygame.freetype.Face.vertical"><tt class="xref py py-meth docutils literal"><span class="pre">Face.vertical()</span></tt></a> attribute.
-Optionally you may specify another point size to use via the &#8216;ptsize&#8217;
-argument, a text rotation via the &#8216;rotation&#8217; argument, or a new text
-style via the &#8216;style&#8217; argument.</p>
+<p>By default, the point size and style set for the face are used
+if not passed as arguments. The text is unrotated unless a non-zero
+rotation value is given.</p>
 <p>If text is a char (byte) string, then its encoding is assumed to be
 <tt class="docutils literal"><span class="pre">LATIN1</span></tt>.</p>
 </dd></dl>

File src/freetype/ft_pixel.h

 
 #include "../surface.h"
 
-#define GET_RGB_VALS(pixel, fmt, r, g, b, a)                            \
+#define UNMAP_RGB_VALUE(pixel, fmt, r, g, b, a)                         \
     (r) = ((pixel) & (fmt)->Rmask) >> (fmt)->Rshift;                    \
     (r) = ((r) << (fmt)->Rloss) + ((r) >> (8 - ((fmt)->Rloss << 1)));   \
     (g) = ((pixel) & (fmt)->Gmask) >> (fmt)->Gshift;                    \
         (a) = 255;                                                      \
     }
 
-#define GET_PALETTE_VALS(pixel, fmt, sr, sg, sb, sa)                    \
+#define UNMAP_PALETTE_INDEX(pixel, fmt, sr, sg, sb, sa)                 \
     (sr) = (fmt)->palette->colors[(Uint8) (pixel)].r;                   \
     (sg) = (fmt)->palette->colors[(Uint8) (pixel)].g;                   \
     (sb) = (fmt)->palette->colors[(Uint8) (pixel)].b;                   \
     }
 
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
-#define GET_PIXEL24(b) ((b)[0] + ((b)[1] << 8) + ((b)[2] << 16))
-#define SET_PIXEL24_RGB(buf,format,r,g,b)                               \
-    *((buf) + ((format)->Rshift >> 3)) = (r);                           \
-    *((buf) + ((format)->Gshift >> 3)) = (g);                           \
-    *((buf) + ((format)->Bshift >> 3)) = (b);
-#define SET_PIXEL24(buf,format,rgb)                                     \
-    *((buf) + ((format)->Rshift >> 3)) = (rgb)[0];                      \
-    *((buf) + ((format)->Gshift >> 3)) = (rgb)[1];                      \
-    *((buf) + ((format)->Bshift >> 3)) = (rgb)[2];
+#define GET_PIXEL24(bufp) ((bufp)[0] + ((bufp)[1] << 8) + ((bufp)[2] << 16))
+#define MAP_PIXEL24(bufp, format, r, g, b)                              \
+    do {                                                                \
+        (bufp)[(format)->Rshift >> 3] = (r);                            \
+        (bufp)[(format)->Gshift >> 3] = (g);                            \
+        (bufp)[(format)->Bshift >> 3] = (b);                            \
+    }                                                                   \
+    while (0)
+#define SET_PIXEL24(bufp, pix)                  \
+    do {                                        \
+        (bufp)[0] = (FT_Byte)(pix);             \
+        (bufp)[1] = (FT_Byte)(pix >> 8);        \
+        (bufp)[2] = (FT_Byte)(pix >> 16);       \
+    }                                           \
+    while (0)
 #else
-#define GET_PIXEL24(b) ((b)[2] + ((b)[1] << 8) + ((b)[0] << 16))
-#define SET_PIXEL24_RGB(buf,format,r,g,b)                               \
-    *((buf) + 2 - ((format)->Rshift >> 3)) = (r);                       \
-    *((buf) + 2 - ((format)->Gshift >> 3)) = (g);                       \
-    *((buf) + 2 - ((format)->Bshift >> 3)) = (b);
-#define SET_PIXEL24(buf,format,rgb)                                     \
-    *((buf) + 2 - ((format)->Rshift >> 3)) = (rgb)[0];                  \
-    *((buf) + 2 - ((format)->Gshift >> 3)) = (rgb)[1];                  \
-    *((buf) + 2 - ((format)->Bshift >> 3)) = (rgb)[2];
+#define GET_PIXEL24(bufp) ((bufp)[2] + ((bufp)[1] << 8) + ((bufp)[0] << 16))
+#define MAP_PIXEL24(bufp, format, r, g, b)                              \
+    do {                                                                \
+        (bufp)[2 - (format)->Rshift >> 3] = (r);                        \
+        (bufp)[2 - (format)->Gshift >> 3] = (g);                        \
+        (bufp)[2 - (format)->Bshift >> 3] = (b);                        \
+    }                                                                   \
+    while (0)
+#define SET_PIXEL24(bufp, pix)                  \
+    do {                                        \
+        (bufp)[2] = (FT_Byte)(pix);             \
+        (bufp)[1] = (FT_Byte)(pix >> 8);        \
+        (bufp)[0] = (FT_Byte)(pix >> 16);       \
+    }                                           \
+    while (0)
 #endif
 
 #endif

File src/freetype/ft_render.c

 #include FT_OUTLINE_H
 
 static void render(FreeTypeInstance *, FaceText *, const FaceRenderMode *,
-                   FaceColor *, FaceSurface *, unsigned, unsigned, FT_Vector *,
-                   FT_Pos, FT_Fixed);
+                   FaceColor *, FaceSurface *, unsigned, unsigned,
+                   FT_Vector *, FT_Pos, FT_Fixed);
 
 int
 _PGFT_CheckStyle(FT_UInt32 style)
      * if bg color exists, paint background
      */
     if (bgcolor) {
-        if (bgcolor->a == 0xFF) {
+        if (bgcolor->a == 255) {
             SDL_Rect    bg_fill;
             FT_UInt32   fillcolor;
 

File src/freetype/ft_render_cb.c

 #   include "surface.h"
 #endif
 
+typedef FT_Byte _T1;
+typedef FT_UInt16 _T2;
+typedef FT_UInt32 _T3;
+typedef FT_UInt32 _T4;
+
 void __render_glyph_GRAY1(int x, int y, FaceSurface *surface,
-                          FT_Bitmap *bitmap, FaceColor *fg_color)
+                          FT_Bitmap *bitmap, FaceColor *color)
 {
     FT_Byte *dst = ((FT_Byte *)surface->buffer) + x + (y * surface->pitch);
     FT_Byte *dst_cpy;
     /*
      * Assumption, target buffer was filled with zeros before any rendering.
      */
-
     for (j = 0; j < bitmap->rows; ++j) {
         src_cpy = src;
         dst_cpy = dst;
 }
 
 void __render_glyph_MONO_as_GRAY1(int x, int y, FaceSurface *surface,
-                                  FT_Bitmap *bitmap, FaceColor *fg_color)
+                                  FT_Bitmap *bitmap, FaceColor *color)
 {
     const int off_x = (x < 0) ? -x : 0;
     const int off_y = (y < 0) ? -y : 0;
     unsigned char*  src_cpy;
     unsigned char*  dst_cpy;
     FT_UInt32       val;
-    FT_Byte shade = fg_color->a;
+    FT_Byte shade = color->a;
 
     src  = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3);
     dst = (unsigned char *)surface->buffer + rx + (ry * surface->pitch);
 }
 
 void __render_glyph_GRAY_as_MONO1(int x, int y, FaceSurface *surface,
-    FT_Bitmap *bitmap, FaceColor *fg_color)
+                                  FT_Bitmap *bitmap, FaceColor *color)
 {
     FT_Byte *dst = ((FT_Byte *)surface->buffer) + x + (y * surface->pitch);
     FT_Byte *dst_cpy;
-    FT_Byte shade = fg_color->a;
+    FT_Byte shade = color->a;
 
     const FT_Byte *src = bitmap->buffer;
     const FT_Byte *src_cpy;
     }
 }
 
-void __fill_glyph_GRAY1(int x, int y, int w, int h,
-        FaceSurface *surface, FaceColor *color)
+void __fill_glyph_GRAY1(int x, int y, int w, int h, FaceSurface *surface,
+                        FaceColor *color)
 {
     int i, j;
     FT_Byte *dst;
 
 #ifdef HAVE_PYGAME_SDL_VIDEO
 
-#define _CREATE_RGB_FILLER(_bpp, _getp, _setp, _blendp)     \
+#define _CREATE_RGB_FILLER(_bpp)                            \
     void __fill_glyph_RGB##_bpp(int x, int y, int w, int h, \
                                 FaceSurface *surface,       \
                                 FaceColor *color)           \
     {                                                       \
+        SDL_PixelFormat *format = surface->format;          \
+        FT_UInt32 bgR, bgG, bgB, bgA;                       \
         int i, j;                                           \
         unsigned char *dst;                                 \
-        FT_UInt32 bgR, bgG, bgB, bgA;                       \
                                                             \
+        if (color->a == 0) {                                \
+            /* Nothing to do. */                            \
+            return;                                         \
+        }                                                   \
         x = MAX(0, x);                                      \
         y = MAX(0, y);                                      \
                                                             \
             unsigned char *_dst = dst;                      \
                                                             \
             for (i = 0; i < w; ++i, _dst += _bpp) {         \
-                FT_UInt32 pixel = (FT_UInt32)_getp;         \
+                FT_UInt32 pixel =                           \
+                    (FT_UInt32)_GET_PIXEL(_bpp, _dst);      \
                                                             \
-                if (_bpp == 1) {                            \
-                    GET_PALETTE_VALS(                       \
-                            pixel, surface->format,         \
-                            bgR, bgG, bgB, bgA);            \
-                }                                           \
-                else {                                      \
-                    GET_RGB_VALS(                           \
-                            pixel, surface->format,         \
+                _UNMAP_PIXEL(_bpp, bgR, bgG, bgB, bgA,      \
+                             format, pixel);                \
+                                                            \
+                ALPHA_BLEND(color->r, color->g,             \
+                            color->b, color->a,             \
                             bgR, bgG, bgB, bgA);            \
                                                             \
-                }                                           \
-                                                            \
-                ALPHA_BLEND(                                \
-                        color->r, color->g, color->b,       \
-                        color->a, bgR, bgG, bgB, bgA);      \
-                                                            \
-                _blendp;                                    \
+                _MAP_PIXEL(_bpp, pixel, format,             \
+                           bgR, bgG, bgB, bgA);             \
+                _SET_PIXEL(_bpp, _dst, pixel);              \
             }                                               \
                                                             \
             dst += surface->pitch;                          \
             if (val & 0x10000) {                            \
                 val = (FT_UInt32)(*_src++ | 0x100);         \
             }                                               \
-            if (val & 0x80) {                               \
-                _code;                                      \
-            }                                               \
+            _code(_bpp, val & 0x80);                        \
             val <<= 1;                                      \
         }                                                   \
                                                             \
         dst += surface->pitch;                              \
     }                                                       \
 
-#define _CREATE_MONO_RENDER(_bpp, _getp, _setp, _blendp)    \
+#define __MONO_RENDER_PIXEL_OPAQUE(_bpp, is_foreground)     \
+    if (is_foreground) {                                    \
+        _SET_PIXEL(_bpp, _dst, full_color);                 \
+    }
+
+#define __MONO_RENDER_PIXEL_ALPHA(_bpp, is_foreground)        \
+    if (is_foreground) {                                      \
+        FT_UInt32 pixel =                                     \
+            (FT_UInt32)_GET_PIXEL(_bpp, _dst);                \
+                                                              \
+        _UNMAP_PIXEL(_bpp, bgR, bgG, bgB, bgA,                \
+                     format, pixel);                          \
+        ALPHA_BLEND(fgR_full, fgG_full,                       \
+                    fgB_full, fgA_full,                       \
+                    bgR, bgG, bgB, bgA);                      \
+        _MAP_PIXEL(_bpp, pixel, format, bgR, bgG, bgB, bgA);  \
+        _SET_PIXEL(_bpp, _dst, pixel);                        \
+    }
+
+#define _CREATE_MONO_RENDER(_bpp)                           \
     void __render_glyph_MONO##_bpp(int x, int y,            \
                                    FaceSurface *surface,    \
                                    FT_Bitmap *bitmap,       \
-                                FaceColor *color)           \
+                                   FaceColor *color)        \
     {                                                       \
         const int off_x = (x < 0) ? -x : 0;                 \
         const int off_y = (y < 0) ? -y : 0;                 \
         const int rx = MAX(0, x);                           \
         const int ry = MAX(0, y);                           \
                                                             \
-        int             i, j, shift;                                    \
-        unsigned char*  src;                                            \
-        unsigned char*  dst;                                            \
-        FT_UInt32       full_color;                                     \
+        SDL_PixelFormat *format = surface->format;                      \
+        int i, j, shift;                                                \
+        unsigned char *src;                                             \
+        unsigned char *dst;                                             \
+        FT_UInt32 fgR_full = color->r;                                  \
+        FT_UInt32 fgG_full = color->g;                                  \
+        FT_UInt32 fgB_full = color->b;                                  \
+        FT_UInt32 fgA_full = color->a;                                  \
+        _T(_bpp) full_color;                                            \
         FT_UInt32 bgR, bgG, bgB, bgA;                                   \
                                                                         \
         src  = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3); \
         dst = (unsigned char *)surface->buffer + (rx * _bpp) +          \
                     (ry * surface->pitch);                              \
                                                                         \
-        full_color = SDL_MapRGBA(surface->format, (FT_Byte)color->r,    \
-                (FT_Byte)color->g, (FT_Byte)color->b, 255);             \
+        _MAP_PIXEL(_bpp, full_color, format,                            \
+                   fgR_full, fgG_full, fgB_full, fgA_full);             \
                                                                         \
         shift = off_x & 7;                                              \
                                                                         \
-        if (color->a == 0xFF) {                                         \
-            __MONO_RENDER_INNER_LOOP(_bpp,                              \
-            {                                                           \
-                _setp;                                                  \
-            });                                                         \
+        if (color->a == SDL_ALPHA_OPAQUE) {                             \
+            __MONO_RENDER_INNER_LOOP(_bpp, __MONO_RENDER_PIXEL_OPAQUE); \
         }                                                               \
-        else if (color->a > 0) {                                        \
-            __MONO_RENDER_INNER_LOOP(_bpp,                              \
-            {                                                           \
-                FT_UInt32 pixel = (FT_UInt32)_getp;                     \
-                                                                        \
-                if (_bpp == 1) {                                        \
-                    GET_PALETTE_VALS(                                   \
-                            pixel, surface->format,                     \
-                            bgR, bgG, bgB, bgA);                        \
-                }                                                       \
-                else {                                                  \
-                    GET_RGB_VALS(                                       \
-                            pixel, surface->format,                     \
-                            bgR, bgG, bgB, bgA);                        \
-                                                                        \
-                }                                                       \
-                                                                        \
-                ALPHA_BLEND(                                            \
-                        color->r, color->g, color->b, color->a,         \
-                        bgR, bgG, bgB, bgA);                            \
-                                                                        \
-                _blendp;                                                \
-            });                                                         \
+        else if (color->a > SDL_ALPHA_TRANSPARENT) {                    \
+            __MONO_RENDER_INNER_LOOP(_bpp, __MONO_RENDER_PIXEL_ALPHA);  \
         }                                                               \
     }
 
-#define _CREATE_RGB_RENDER(_bpp, _getp, _setp, _blendp)                 \
+#define _CREATE_RGB_RENDER(_bpp)                                        \
     void __render_glyph_RGB##_bpp(int x, int y, FaceSurface *surface,   \
-        FT_Bitmap *bitmap, FaceColor *color)                            \
+                                  FT_Bitmap *bitmap, FaceColor *color)  \
     {                                                                   \
         const int off_x = (x < 0) ? -x : 0;                             \
         const int off_y = (y < 0) ? -y : 0;                             \
         const int rx = MAX(0, x);                                       \
         const int ry = MAX(0, y);                                       \
                                                                         \
+        SDL_PixelFormat *format = surface->format;                      \
         FT_Byte *dst = ((FT_Byte*)surface->buffer) + (rx * _bpp) +      \
                         (ry * surface->pitch);                          \
         FT_Byte *_dst;                                                  \
                                 (off_y * bitmap->pitch);                \
         const FT_Byte *_src;                                            \
                                                                         \
-	_DECLARE_full_color##_bpp(surface, color)			\
-        /*                                                              \
-        const FT_UInt32 full_color =                                    \
-            SDL_MapRGBA(surface->format, (FT_Byte)color->r,             \
-                    (FT_Byte)color->g, (FT_Byte)color->b, 255);         \
-	*/                                                              \
+        FT_UInt32 bgR, bgG, bgB, bgA;                                   \
+        FT_UInt32 fgR_full = color->r;                                  \
+        FT_UInt32 fgG_full = color->g;                                  \
+        FT_UInt32 fgB_full = color->b;                                  \
+        FT_UInt32 fgA_full = color->a;                                  \
+        _T(_bpp) full_color;                                            \
+        int j, i;                                                       \
                                                                         \
-        FT_UInt32 bgR, bgG, bgB, bgA;                                   \
-        int j, i;                                                       \
+        _MAP_PIXEL(_bpp, full_color, format,                            \
+                   fgR_full, fgG_full, fgB_full, fgA_full);             \
                                                                         \
         for (j = ry; j < max_y; ++j) {                                  \
             _src = src;                                                 \
             _dst = dst;                                                 \
                                                                         \
             for (i = rx; i < max_x; ++i, _dst += _bpp) {                \
-                FT_UInt32 alpha = (*_src++);                            \
-                alpha = (alpha * color->a) / 255;                       \
+                FT_UInt32 alpha = (*_src++) * fgA_full / 255;           \
                                                                         \
-                if (alpha == 0xFF) {                                    \
-                    _setp;                                              \
+                if (alpha == SDL_ALPHA_OPAQUE) {                        \
+                    _SET_PIXEL(_bpp, _dst, full_color);                 \
                 }                                                       \
-                else if (alpha > 0) {                                   \
-                    FT_UInt32 pixel = (FT_UInt32)_getp;                 \
+                else if (alpha != SDL_ALPHA_TRANSPARENT) {              \
+                    FT_UInt32 pixel =                                   \
+                        (FT_UInt32)_GET_PIXEL(_bpp, _dst);              \
                                                                         \
-                if (_bpp == 1) {                                        \
-                    GET_PALETTE_VALS(                                   \
-                            pixel, surface->format,                     \
-                            bgR, bgG, bgB, bgA);                        \
-                }                                                       \
-                else {                                                  \
-                    GET_RGB_VALS(                                       \
-                            pixel, surface->format,                     \
-                            bgR, bgG, bgB, bgA);                        \
+                    _UNMAP_PIXEL(_bpp, bgR, bgG, bgB, bgA,              \
+                                 format, pixel);                        \
                                                                         \
-                }                                                       \
-                                                                        \
-                    ALPHA_BLEND(                                        \
-                            color->r, color->g, color->b, alpha,        \
-                            bgR, bgG, bgB, bgA);                        \
-                                                                        \
-                    _blendp;                                            \
+                    if (bgA == 0) {                                     \
+                        _SET_PIXEL(_bpp, _dst, full_color);             \
+                    }                                                   \
+                    else {                                              \
+                        ALPHA_BLEND(fgR_full, fgG_full, fgB_full,       \
+                                    alpha,                              \
+                                    bgR, bgG, bgB, bgA);                \
+                        _MAP_PIXEL(_bpp, pixel, format,                 \
+                                   bgR, bgG, bgB, bgA);                 \
+                        _SET_PIXEL(_bpp, _dst, pixel);                  \
+                    }                                                   \
                 }                                                       \
             }                                                           \
                                                                         \
         }                                                               \
     }
 
-/* These macros removes a gcc unused variable warning for __render_glyph_RGB3 */
-#define _DECLARE_full_color(s, c) const FT_UInt32 full_color =          \
-    SDL_MapRGBA((s)->format, (FT_Byte)(c)->r, (FT_Byte)(c)->g,          \
-                (FT_Byte)(c)->b, 255);
-#define _DECLARE_full_color1(s, c) _DECLARE_full_color(s, c)
-#define _DECLARE_full_color2(s, c) _DECLARE_full_color(s, c)
-#define _DECLARE_full_color3(s, c)
-#define _DECLARE_full_color4(s, c) _DECLARE_full_color(s, c)
+#define _T(_bpp) _T##_bpp
 
+#define _GET_PIXEL(_bpp, _sp) _GET_PIXEL##_bpp(_sp)
+#define _GET_PIXELT(_T, _sp) (*(_T *)(_sp))
+#define _GET_PIXEL1(_sp) _GET_PIXELT(_T1, _sp)
+#define _GET_PIXEL2(_sp) _GET_PIXELT(_T2, _sp)
+#define _GET_PIXEL3(_sp) GET_PIXEL24((FT_Byte *)(_sp))
+#define _GET_PIXEL4(_sp) _GET_PIXELT(_T4, _sp)
 
-#define _SET_PIXEL_24   \
-    SET_PIXEL24_RGB(_dst, surface->format, color->r, color->g, color->b);
+#define _SET_PIXEL(_bpp, _bufp, _s) _SET_PIXEL##_bpp(_bufp, _s)
+#define _SET_PIXELT(_T, _bufp, _s) (*(_T *)(_bufp)) = (_T)(_s)
+#define _SET_PIXEL1(_bufp, _s) _SET_PIXELT(_T1, _bufp, _s)
+#define _SET_PIXEL2(_bufp, _s) _SET_PIXELT(_T2, _bufp, _s)
+#define _SET_PIXEL3(_bufp, _s) SET_PIXEL24((FT_Byte *)(_bufp), _s)
+#define _SET_PIXEL4(_bufp, _s) _SET_PIXELT(_T4, _bufp, _s)
 
-#define _BLEND_PIXEL_24 \
-    SET_PIXEL24_RGB(_dst, surface->format, bgR, bgG, bgB);
+#define _UNMAP_PIXEL(_bpp, _r, _g, _b, _a, _fmtp, _pix) \
+    _UNMAP_PIXEL##_bpp(_r, _g, _b, _a, _fmtp, _pix)
+#define _UNMAP_PIXEL1(_r, _g, _b, _a, _fmtp, _i)        \
+    UNMAP_PALETTE_INDEX(_i, _fmtp, _r, _g, _b, _a)
+#define _UNMAP_PIXEL2(_r, _g, _b, _a, _fmtp, _pix)      \
+    UNMAP_RGB_VALUE(_pix, _fmtp, _r, _g, _b, _a)
+#define _UNMAP_PIXEL3(_r, _g, _b, _a, _fmtp, _pix)      \
+    UNMAP_RGB_VALUE(_pix, _fmtp, _r, _g, _b, _a)
+#define _UNMAP_PIXEL4(_r, _g, _b, _a, _fmtp, _pix)      \
+    UNMAP_RGB_VALUE(_pix, _fmtp, _r, _g, _b, _a)
 
-#define _SET_PIXEL(T) \
-    *(T*)_dst = (T)full_color;
+#define _MAP_PIXEL(_bpp, _pix, _fmtp, _r, _g, _b, _a)  \
+    _MAP_PIXEL##_bpp(_pix, _fmtp, _r, _g, _b, _a)
+#define _MAP_PIXELT(_T, _pix, _fmtp, _r, _g, _b, _a)    \
+    do {                                                \
+        _pix = (_T)(                                    \
+            (((_r) >> _fmtp->Rloss) << _fmtp->Rshift) | \
+            (((_g) >> _fmtp->Gloss) << _fmtp->Gshift) | \
+            (((_b) >> _fmtp->Bloss) << _fmtp->Bshift) | \
+            (((_a) >> _fmtp->Aloss) << _fmtp->Ashift  & \
+             surface->format->Amask));                  \
+    }                                                   \
+    while (0)
+#define _MAP_PIXEL_GENERIC(_T, _pix, _fmtp, _r, _g, _b, _a)             \
+    do {                                                                \
+        _pix = (_T)(SDL_MapRGB((_fmtp), (FT_Byte)(_r),                  \
+                               (FT_Byte)(_g), (FT_Byte)(_b)));          \
+    }                                                                   \
+    while (0)
+#define _MAP_PIXEL1(_pix, _fmtp, _r, _g, _b, _a)                \
+    _MAP_PIXEL_GENERIC(_T1, _pix, _fmtp, _r, _g, _b, _a)
+#define _MAP_PIXEL2(_pix, _fmtp, _r, _g, _b, _a)        \
+    _MAP_PIXELT(_T2, _pix, _fmtp, _r, _g, _b, _a)
+#define _MAP_PIXEL3(_pix, _fmtp, _r, _g, _b, _a)                \
+    MAP_PIXEL24((FT_Byte *)(&(_pix)), _fmtp, _r, _g, _b)
+#define _MAP_PIXEL4(_pix, _fmtp, _r, _g, _b, _a)        \
+    _MAP_PIXELT(_T4, _pix, _fmtp, _r, _g, _b, _a)
 
-#define _BLEND_PIXEL(T) *((T*)_dst) = (T)(                          \
-    ((bgR >> surface->format->Rloss) << surface->format->Rshift) |  \
-    ((bgG >> surface->format->Gloss) << surface->format->Gshift) |  \
-    ((bgB >> surface->format->Bloss) << surface->format->Bshift) |  \
-    ((bgA >> surface->format->Aloss) << surface->format->Ashift  &  \
-     surface->format->Amask)                                        )
+_CREATE_RGB_RENDER(4)
+_CREATE_RGB_RENDER(3)
+_CREATE_RGB_RENDER(2)
+_CREATE_RGB_RENDER(1)
 
-#define _BLEND_PIXEL_GENERIC(T) *(T*)_dst = (T)(    \
-    SDL_MapRGB(surface->format,                     \
-        (FT_Byte)bgR, (FT_Byte)bgG, (FT_Byte)bgB)   )
+_CREATE_MONO_RENDER(4)
+_CREATE_MONO_RENDER(3)
+_CREATE_MONO_RENDER(2)
+_CREATE_MONO_RENDER(1)
 
-#define _GET_PIXEL(T)    (*((T*)_dst))
-
-_CREATE_RGB_RENDER(4,  _GET_PIXEL(FT_UInt32),   _SET_PIXEL(FT_UInt32),  _BLEND_PIXEL(FT_UInt32))
-_CREATE_RGB_RENDER(3,  GET_PIXEL24(_dst),       _SET_PIXEL_24,          _BLEND_PIXEL_24)
-_CREATE_RGB_RENDER(2,  _GET_PIXEL(FT_UInt16),   _SET_PIXEL(FT_UInt16),  _BLEND_PIXEL(FT_UInt16))
-_CREATE_RGB_RENDER(1,  _GET_PIXEL(FT_Byte),     _SET_PIXEL(FT_Byte),    _BLEND_PIXEL_GENERIC(FT_Byte))
-
-_CREATE_MONO_RENDER(4,  _GET_PIXEL(FT_UInt32),   _SET_PIXEL(FT_UInt32),  _BLEND_PIXEL(FT_UInt32))
-_CREATE_MONO_RENDER(3,  GET_PIXEL24(_dst),       _SET_PIXEL_24,          _BLEND_PIXEL_24)
-_CREATE_MONO_RENDER(2,  _GET_PIXEL(FT_UInt16),   _SET_PIXEL(FT_UInt16),  _BLEND_PIXEL(FT_UInt16))
-_CREATE_MONO_RENDER(1,  _GET_PIXEL(FT_Byte),     _SET_PIXEL(FT_Byte),    _BLEND_PIXEL_GENERIC(FT_Byte))
-
-_CREATE_RGB_FILLER(4,  _GET_PIXEL(FT_UInt32),   _SET_PIXEL(FT_UInt32),  _BLEND_PIXEL(FT_UInt32))
-_CREATE_RGB_FILLER(3,  GET_PIXEL24(_dst),       _SET_PIXEL_24,          _BLEND_PIXEL_24)
-_CREATE_RGB_FILLER(2,  _GET_PIXEL(FT_UInt16),   _SET_PIXEL(FT_UInt16),  _BLEND_PIXEL(FT_UInt16))
-_CREATE_RGB_FILLER(1,  _GET_PIXEL(FT_Byte),     _SET_PIXEL(FT_Byte),    _BLEND_PIXEL_GENERIC(FT_Byte))
+_CREATE_RGB_FILLER(4)
+_CREATE_RGB_FILLER(3)
+_CREATE_RGB_FILLER(2)
+_CREATE_RGB_FILLER(1)
 #endif

File src/freetype/ft_wrap.h

 void __render_glyph_RGB4(int, int, FaceSurface *, FT_Bitmap *, FaceColor *);
 
 void __render_glyph_GRAY1(int, int, FaceSurface *, FT_Bitmap *, FaceColor *);
-void __render_glyph_MONO_as_GRAY1(int, int, FaceSurface *,
-                                  FT_Bitmap *, FaceColor *);
-void __render_glyph_GRAY_as_MONO1(int, int, FaceSurface *,
-                                  FT_Bitmap *, FaceColor *);
+void __render_glyph_MONO_as_GRAY1(int, int, FaceSurface *, FT_Bitmap *,
+                                  FaceColor *);
+void __render_glyph_GRAY_as_MONO1(int, int, FaceSurface *, FT_Bitmap *,
+                                  FaceColor *);
 
 
 /**************************************** Face text management ***************/

File test/freetype_test.py

             face.antialiased = save_antialiased
 
     def test_freetype_Face_render_to_mono(self):
-        # Rendering to an existing target surface is equivalent to
-        # blitting a surface returned by Face.render with the target.
+        # Blitting is done in two stages. First the target is alpha filled
+        # with the background color, if any. Second, the foreground
+        # color is alpha blitted to the background.
         face = self._TEST_FONTS['sans']
         text = " ."
         rect = face.get_rect(text, ptsize=24)
         size = rect.size
         fg = pygame.Surface((1, 1), pygame.SRCALPHA, 32)
         bg = pygame.Surface((1, 1), pygame.SRCALPHA, 32)
+        surrogate = pygame.Surface((1, 1), pygame.SRCALPHA, 32)
         surfaces = [pygame.Surface(size, 0, 8),
                     pygame.Surface(size, 0, 16),
                     pygame.Surface(size, pygame.SRCALPHA, 16),
             (128, 97, 213),
             (128, 97, 213, 60)]
         fg_colors = [pygame.Color(*c) for c in fg_colors]
-        self.assertEqual(len(surfaces), len(fg_colors))  # safety check
+        self.assertEqual(len(surfaces), len(fg_colors))  # integrity check
         bg_colors = [
             surfaces[0].get_palette_at(4),
             surfaces[1].unmap_rgb(surfaces[1].map_rgb((220, 20, 99))),
             (255, 120, 13),
             (255, 120, 13, 180)]
         bg_colors = [pygame.Color(*c) for c in bg_colors]
-        self.assertEqual(len(surfaces), len(bg_colors))  # safety check
+        self.assertEqual(len(surfaces), len(bg_colors))  # integrity check
 
         save_antialiased = face.antialiased
         face.antialiased = False
                 bg_color = bg_colors[i]
                 bg.set_at((0, 0), bg_color)
                 fg.set_at((0, 0), fg_color)
-                bg.blit(fg, (0, 0))
-                surf.blit(bg, (0, 0))
-                r_fg_color = surf.get_at((0, 0))
-                surf.set_at((0, 0), fill_color)
+                if surf.get_bitsize() == 24:
+                    # For a 24 bit target surface test against Pygame's alpha
+                    # blit as there appears to be a problem with SDL's alpha
+                    # blit:
+                    #
+                    # self.assertEqual(surf.get_at(bottomright), r_fg_color)
+                    #
+                    # raises
+                    #
+                    # AssertionError: (128, 97, 213, 255) != (129, 98, 213, 255)
+                    #
+                    surrogate.set_at((0, 0), fill_color)
+                    surrogate.blit(bg, (0, 0))
+                    r_bg_color = surrogate.get_at((0, 0))
+                    surrogate.blit(fg, (0, 0))
+                    r_fg_color = surrogate.get_at((0, 0))
+                else:
+                    # Surface blit values for comparison.
+                    surf.blit(bg, (0, 0))
+                    r_bg_color = surf.get_at((0, 0))
+                    surf.blit(fg, (0, 0))
+                    r_fg_color = surf.get_at((0, 0))
+                    surf.set_at((0, 0), fill_color)
                 rrect = face.render_to(surf, (0, 0), text, fg_color,
                                        bg_color, ptsize=24)
                 bottomleft = 0, rrect.height - 1
-                self.assertEqual(surf.get_at(bottomleft), bg_color)
-                bottomleft = rrect.width - 1, rrect.height - 1
+                self.assertEqual(surf.get_at(bottomleft), r_bg_color)
+                bottomright = rrect.width - 1, rrect.height - 1
                 self.assertEqual(surf.get_at(bottomright), r_fg_color)
         finally:
             face.antialiased = save_antialiased