Commits

Lenard Lindstrom committed fc95cbb

freetype: Get antialiased option working again, but as rendering of a mono bitmap. Method render now returns a SRCALPHA surface. Method render_raw now has a style argument; it also correctly renders overlapping glyphs by doing alpha blits

  • Participants
  • Parent commits bfd169b

Comments (0)

Files changed (7)

docs/reST/ref/freetype.rst

    .. method:: render_raw
 
       | :sl:`Renders text as a string of bytes`
-      | :sg:`render_raw(text, ptsize=default) -> (bytes, (int, int))`
+      | :sg:`render_raw(text, style=STYLE_DEFAULT, rotation=0, ptsize=default) -> (bytes, (int, int))`
 
       Like ``Font.render(None, ...)`` but the tuple returned is an 8 bit
       monochrome string of bytes and its size. The forground color is 255, the
     /* keyword list */
     static char *kwlist[] = 
     { 
-        "text", "rotation", "ptsize", NULL
+        "text", "style", "rotation", "ptsize", NULL
     };
 
     PyFreeTypeFont *font = (PyFreeTypeFont *)self;
     PGFT_String *text;
     int rotation = 0;
     int ptsize = -1;
+    int style = FT_STYLE_DEFAULT;
 
     /* output arguments */
     PyObject *rbuffer = NULL;
     FreeTypeInstance *ft;
     ASSERT_GRAB_FREETYPE(ft, NULL);
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwlist,
-                                     &textobj, &rotation, &ptsize))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist,
+                                     &textobj, &style, &rotation, &ptsize))
         return NULL;
 
     /* Encode text */
      * rotation/styles/vertical text
      */
     if (PGFT_BuildRenderMode(ft, font, 
-                &render, ptsize, FT_STYLE_NORMAL, rotation) != 0)
+                &render, ptsize, style, rotation) != 0)
     {
         PGFT_FreeString(text);
         return NULL;
     FontMetrics metrics;
     PyObject *rect_obj;
 
-    FontColor fg_color, bg_color;
+    FontColor fg_color;
+    FontColor bg_color;
     FontRenderMode render;
 
     FreeTypeInstance *ft;

src/freetype/ft_metrics.c

-/*
-  pygame - Python Game Library
-  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
-#define NO_PYGAME_C_API
-
-#include "ft_wrap.h"
-#include FT_MODULE_H
-
-extern FT_Matrix PGFT_SlantMatrix;
-
-int PGFT_GetMetrics(FreeTypeInstance *ft, PyFreeTypeFont *font,
-                    PGFT_char character, const FontRenderMode *render,
-                    long *minx, long *maxx, long *miny, long *maxy,
-                    double *advance_x, double *advance_y)
-{ 
-    FontGlyph *     glyph = NULL;
-
-    glyph = PGFT_Cache_FindGlyph(ft, &PGFT_INTERNALS(font)->cache, 
-                                 character, render);
-    
-    if (!glyph)
-    {
-        return -1;
-    }
-
-    *minx = (long)glyph->image->left;
-    *maxx = (long)(glyph->image->left + glyph->image->bitmap.width);
-    *maxy = (long)glyph->image->top;
-    *miny = (long)(glyph->image->top - glyph->image->bitmap.rows);
-    *advance_x = (double)(glyph->h_metrics.advance_rotated.x / 64.0);
-    *advance_y = (double)(glyph->h_metrics.advance_rotated.y / 64.0);
-
-    return 0;
-}
-
-int
-PGFT_GetSurfaceSize(FreeTypeInstance *ft, PyFreeTypeFont *font,
-        const FontRenderMode *render, FontText *text, 
-        int *width, int *height)
-{
-    *width = text->width;
-    *height = text->height;
-    return 0;
-}
-
-int
-PGFT_GetTopLeft(FontText *text, int *top, int *left)
-{
-    *top = text->top;
-    *left = text->left;
-    return 0;
-}
-
-int
-PGFT_GetTextSize(FreeTypeInstance *ft, PyFreeTypeFont *font,
-    const FontRenderMode *render, PGFT_String *text, int *w, int *h)
-{
-    FontText *font_text;
-
-    font_text = PGFT_LoadFontText(ft, font, render, text);
-
-    if (!font_text)
-        return -1;
-
-    return PGFT_GetSurfaceSize(ft, font, render, font_text, w, h);
-}

src/freetype/ft_render.c

 #include FT_MODULE_H
 #include FT_OUTLINE_H
 
-typedef void (* FontRenderPtr)(int, int, FontSurface *, FT_Bitmap *, FontColor *);
-typedef void (* FontFillPtr)(int, int, int, int, FontSurface *, FontColor *);
-
 #define SLANT_FACTOR    0.22
 FT_Matrix PGFT_SlantMatrix = 
 {
     0,          (1 << 16) 
 };
 
-FT_Fixed PGFT_GetBoldStrength(FT_Face face)
-{
-    /* const float bold_factor = 0.058f; */
-    const float bold_factor = 0.06f;
-    FT_Fixed bold_str;
-
-    bold_str = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale);
-    bold_str = (FT_Fixed)((float)bold_str * bold_factor);
-
-    return bold_str;
-}
+static int _PGFT_Render_INTERNAL(FreeTypeInstance *ft, PyFreeTypeFont *font, 
+                                 FontText *text, const FontRenderMode *render,
+                                 FontColor *fg_color, FontSurface *surface);
 
 int PGFT_CheckStyle(FT_UInt32 style)
 {
 
     font_surf.format = surface->format;
 
-    if (render->render_flags & FT_RFLAG_ANTIALIAS)
-        font_surf.render = __SDLrenderFuncs[surface->format->BytesPerPixel];
-    else
-        font_surf.render = __MONOrenderFuncs[surface->format->BytesPerPixel];
-
+    font_surf.render_gray = __SDLrenderFuncs[surface->format->BytesPerPixel];
+    font_surf.render_mono = __MONOrenderFuncs[surface->format->BytesPerPixel];
     font_surf.fill = __RGBfillFuncs[surface->format->BytesPerPixel];
 
     /* 
     int locked = 0;
     FT_UInt32 fillcolor;
     SDL_Surface *surface = NULL;
+    FT_UInt32 surface_flags = SDL_SWSURFACE | SDL_SRCALPHA;
 
     FontSurface font_surf;
     FontText *font_text;
         height = PGFT_Face_GetHeight(ft, font);
     }
         
-    surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 
-            width, height,
-            32, rmask, gmask, bmask, amask);
-
+    surface = SDL_CreateRGBSurface(surface_flags, width, height,
+				   32, rmask, gmask, bmask, amask);
     if (!surface)
     {
         PyErr_NoMemory(); /* Everything else should be Okay */
     font_surf.pitch = surface->pitch / sizeof(FT_UInt32);
 
     font_surf.format = surface->format;
-    font_surf.render = __render_glyph_RGB4;
+    font_surf.render_gray = __render_glyph_RGB4;
+    font_surf.render_mono = __render_glyph_MONO4;
     font_surf.fill = __fill_glyph_RGB4;
 
     /*
     surf.height = height;
 
     surf.format = NULL;
-    surf.render = __render_glyph_ByteArray;
+    surf.render_gray = __render_glyph_ByteArray;
+    surf.render_mono = __render_glyph_ByteArray_MONO;
 
     if (_PGFT_Render_INTERNAL(ft, font, font_text, render, 0x0, &surf) != 0)
     {
  * New rendering algorithm (rotation + veritical drawing)
  *
  *********************************************************/
-int _PGFT_Render_INTERNAL(FreeTypeInstance *ft, PyFreeTypeFont *font, 
-    FontText *text, const FontRenderMode *render, FontColor *fg_color,
-    FontSurface *surface)
+static int _PGFT_Render_INTERNAL(FreeTypeInstance *ft, PyFreeTypeFont *font, 
+                                 FontText *text, const FontRenderMode *render,
+                                 FontColor *fg_color, FontSurface *surface)
 {
     FT_Pos top;
     FT_Pos left;
     FontGlyph **glyphs = text->glyphs;
     FT_BitmapGlyph image;
     FT_Vector *posns = text->posns;
+    FontRenderPtr render_gray = surface->render_gray;
+    FontRenderPtr render_mono = surface->render_mono;
     int error = 0;
+    
 
     if (length <= 0)
         return error;
         image = glyphs[n]->image;
         x = PGFT_TRUNC(PGFT_CEIL(left + posns[n].x));
         y = PGFT_TRUNC(PGFT_CEIL(top + posns[n].y));
-        surface->render(x, y, surface, &(image->bitmap), fg_color);
+        if (image->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
+            render_gray(x, y, surface, &(image->bitmap), fg_color);
+        else
+            render_mono(x, y, surface, &(image->bitmap), fg_color);
     }
 
     if (text->underline_size > 0)
     }
     return error;
 }
-

src/freetype/ft_render_cb.c

     const FT_Byte *src = bitmap->buffer;
     const FT_Byte *src_cpy;
 
+    FT_Byte src_byte;
     int j, i;
 
+    /*
+     * Assumption, target buffer was initialized to zeros before any rendering.
+     */
+
     for (j = 0; j < bitmap->rows; ++j)
     {
         src_cpy = src;
         dst_cpy = dst;
 
         for (i = 0; i < bitmap->width; ++i)
-            *dst_cpy++ = (FT_Byte)(*src_cpy++);
+        {
+            src_byte = *src_cpy;
+            if (src_byte)
+            {
+                *dst_cpy = src_byte + *dst_cpy - src_byte * *dst_cpy / 255;
+            }
+            ++src_cpy;
+            ++dst_cpy;
+        }
 
         dst += surface->pitch;
         src += bitmap->pitch;
     }
 }
 
+void __render_glyph_ByteArray_MONO(int x, int y, FontSurface *surface,
+				   FT_Bitmap *bitmap, FontColor *fg_color)
+{
+    const int off_x = (x < 0) ? -x : 0;
+    const int off_y = (y < 0) ? -y : 0;
+
+    const int max_x = MIN(x + bitmap->width, surface->width);
+    const int max_y = MIN(y + bitmap->rows, surface->height);
+
+    const int rx = MAX(0, x);
+    const int ry = MAX(0, y);
+
+    int             i, j, shift;
+    unsigned char*  src;
+    unsigned char*  dst;
+    unsigned char*  _src;
+    unsigned char*  _dst;
+    FT_UInt32       val;
+
+    src  = bitmap->buffer + (off_y * bitmap->pitch) + (off_x >> 3);
+    dst = (unsigned char *)surface->buffer + rx + (ry * surface->pitch);
+
+    shift = off_x & 7;
+
+    for (j = ry; j < max_y; ++j)
+    {
+        _src = src;
+        _dst = dst;
+         val = (FT_UInt32)(*_src++ | 0x100) << shift;
+
+        for (i = rx; i < max_x; ++i, ++_dst)
+        {
+            if (val & 0x10000)
+                val = (FT_UInt32)(*_src++ | 0x100);
+
+            if (val & 0x80)
+                *_dst = '\377';
+
+            val   <<= 1;
+        }
+
+        src += bitmap->pitch;
+        dst += surface->pitch;
+    }
+}
+
 #ifdef HAVE_PYGAME_SDL_VIDEO
 
 #define _CREATE_RGB_FILLER(_bpp, _getp, _setp, _blendp)     \

src/freetype/ft_text.c

     FTC_CMapCache charmap;
 } FontTextContext;
 
+#define BOLD_STRENGTH_D (0.65)
+#define PIXEL_SIZE ((FT_Fixed)64)
+#define BOLD_STRENGTH ((FT_Fixed)(BOLD_STRENGTH_D * PIXEL_SIZE))
+#define BOLD_ADVANCE (BOLD_STRENGTH * (FT_Fixed)4)
+#define UNICODE_SPACE ((PGFT_char)' ')
+
 static FT_UInt32 GetLoadFlags(const FontRenderMode *);
 static void fill_metrics(FontMetrics *metrics,
                          FT_Pos bearing_x, FT_Pos bearing_y,
     PGFT_char * ch;
 
     FT_Fixed    y_scale;
-    FT_Fixed    bold_str = 0;
 
     FontText    *ftext = &(PGFT_INTERNALS(font)->active_text);
     FontGlyph   *glyph = NULL;
     FT_Pos      text_width;
     FT_Pos      text_height;
     FT_Pos      top = PGFT_MIN_6;
+    FT_Fixed    bold_str = render->style & FT_STYLE_BOLD ? BOLD_STRENGTH : 0;
 
     FT_Error    error = 0;
 
 
     int oblique = render->style & FT_STYLE_OBLIQUE;
     int embolden = render->style & FT_STYLE_BOLD;
+    FT_Render_Mode rmode = (render->render_flags & FT_RFLAG_ANTIALIAS ?
+                            FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO);
+    FT_Fixed bold_str = 0;
+    FT_Fixed bold_advance = 0;
     FT_Glyph image = NULL;
 
     FT_Glyph_Metrics *ft_metrics;
     FontTextContext *context = (FontTextContext *)internal;
 
     FT_UInt32 load_flags;
-    FT_Pos bold_str = 0;
-    FT_Pos bold_advance = 0;
     FT_UInt gindex;
 
     FT_Fixed rotation_angle = render->rotation_angle;
         FT_Get_Glyph(context->face->glyph, &image))
         goto cleanup;
 
-    if (embolden)
+    if (embolden && character != UNICODE_SPACE)
     {
-        bold_str = PGFT_GetBoldStrength(context->face);
-        /* bold_advance = (bold_str * 3) / 2; */
-        bold_advance = 4 * bold_str;
-        if (FT_Outline_Embolden(&((FT_OutlineGlyph)image)->outline, bold_str))
+        if (FT_Outline_Embolden(&((FT_OutlineGlyph)image)->outline,
+				BOLD_STRENGTH))
             goto cleanup;
+	bold_str = BOLD_STRENGTH;
+	bold_advance = BOLD_ADVANCE;
     }
 
     /*
     /*
      * Finished with transformations, now replace with a bitmap
      */
-    error = FT_Glyph_To_Bitmap(&image, FT_RENDER_MODE_NORMAL, 0, 1);
+    error = FT_Glyph_To_Bitmap(&image, rmode, 0, 1);
     if (error)
     {
         goto cleanup;
 
     if (render->render_flags & FT_RFLAG_HINTED)
     {
-        load_flags |= ((render->render_flags & FT_RFLAG_ANTIALIAS) ?
-                       FT_LOAD_TARGET_NORMAL :
-                       FT_LOAD_TARGET_MONO);
+        load_flags |= FT_LOAD_TARGET_NORMAL;
+        /* load_flags |= ((render->render_flags & FT_RFLAG_ANTIALIAS) ? */
+        /*                FT_LOAD_TARGET_NORMAL : */
+        /*                FT_LOAD_TARGET_MONO); */
     }
     else
     {

src/freetype/ft_wrap.h

     FT_Byte a;
 } FontColor;
 
-typedef struct __fontsurface
-{
-    void *buffer;
-
-    FT_Vector offset;
-
-    int width;
-    int height;
-    int pitch;
-
-    SDL_PixelFormat *format;
-
-    void (* render) (int, int, struct __fontsurface *, FT_Bitmap *, FontColor *);
-    void (* fill)   (int, int, int, int, struct __fontsurface *, FontColor *);
-
-} FontSurface;
-
 typedef struct __rendermode
 {
     FT_UInt16   pt_size;
     FontCache  glyph_cache;
 } FontText;
 
+struct __fontsurface;
+
+typedef void (* FontRenderPtr)(int, int, struct __fontsurface *,
+			       FT_Bitmap *, FontColor *);
+typedef void (* FontFillPtr)(int, int, int, int, struct __fontsurface *,
+			     FontColor *);
+
+typedef struct __fontsurface
+{
+    void *buffer;
+
+    FT_Vector offset;
+
+    int width;
+    int height;
+    int pitch;
+
+    SDL_PixelFormat *format;
+
+    FontRenderPtr render_gray;
+    FontRenderPtr render_mono;
+    FontFillPtr fill;
+
+} FontSurface;
+
 #define PGFT_INTERNALS(f) ((FontInternals *)(f->_internals))
 typedef struct FontInternals_
 {
                 PyFreeTypeFont *font, FontRenderMode *mode, int pt_size, 
                 int style, int rotation);
 
-FT_Fixed    PGFT_GetBoldStrength(FT_Face face);
-
-int         _PGFT_Render_INTERNAL(FreeTypeInstance *ft, PyFreeTypeFont *font, 
-                FontText *text, const FontRenderMode *render, FontColor *fg_color, 
-                FontSurface *surface);
-
 int PGFT_CheckStyle(FT_UInt32 style);
 
 
 void __render_glyph_RGB4(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, FontColor *color);
 
 void __render_glyph_ByteArray(int x, int y, FontSurface *surface, FT_Bitmap *bitmap, FontColor *color);
+void __render_glyph_ByteArray_MONO(int x, int y, FontSurface *surface,
+				   FT_Bitmap *bitmap, FontColor *fg_color);
 
 /******************************************************** Font text management ****/
 int PGFT_FontTextInit(FreeTypeInstance *ft, PyFreeTypeFont *font);