Hi all,

Attached is a patch to add support to create synthetic bold variants of a font 
when using FreeType fonts. It uses FreeType's built in emboldening function but 
I've added the ability to specify the boldening factor (the default is 1).

Set DFFA_STYLE_SYNTH_BOLD when loading the font and use DFDESC_EMBOLDEN if you 
have set the embolden_factor member of the DFBFontDescription struct. The 
embolden_factor is a 16.16 fixed point integer, so you can use the 
DFB_EMBOLDEN_FACTOR macro to set it:

DFBFontDescription font_dsc;

font_dsc.flags |= DFDESC_EMBOLDEN;
font_dsc.attributes |= DFFA_STYLE_SYNTH_BOLD;
font_dsc.embolden_factor = DFB_EMBOLDEN_FACTOR(0.65);

Let me know if there are issues/problems/concerns.

Pedro Navarro
From fc1ed787a4a89bdf720f809da565c34a02da629b Mon Sep 17 00:00:00 2001
From: Pedro Navarro <pnava...@netflix.com>
Date: Thu, 7 Jul 2011 18:09:26 -0700
Subject: [PATCH] Support for synthetic bold generation for FreeType fonts

---
 include/directfb.h                           |    9 +++
 interfaces/IDirectFBFont/idirectfbfont_ft2.c |   99 ++++++++++++++++++++++++++
 2 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/include/directfb.h b/include/directfb.h
index ab94b10..e8f7ca3 100644
--- a/include/directfb.h
+++ b/include/directfb.h
@@ -1116,6 +1116,7 @@ typedef enum {
      DFFA_STYLE_ITALIC        = 0x00000200,  /* load italic style */
      DFFA_VERTICAL_LAYOUT     = 0x00000400,  /* load vertical layout */
      DFFA_STYLE_BOLD          = 0x00000800,  /* load bold style */
+     DFFA_STYLE_SYNTH_BOLD    = 0x00001000   /* generate bold style */
 } DFBFontAttributes;
 
 /*
@@ -1134,6 +1135,7 @@ typedef enum {
      DFDESC_OUTLINE_WIDTH     = 0x00000080,  /* outline width is set */
      DFDESC_OUTLINE_OPACITY   = 0x00000100,  /* outline opacity is set */
      DFDESC_ROTATION          = 0x00000200,  /* rotation is set */
+     DFDESC_EMBOLDEN          = 0x00000400   /* embolden factor is set */
 } DFBFontDescriptionFlags;
 
 /*
@@ -1157,6 +1159,10 @@ typedef enum {
  *
  * The rotation value is a 0.24 fixed point number of rotations.  Use the macros DFB_DEGREES
  * and DFB_RADIANS to convert from those units.
+ *
+ * The emboldening factor is a 0.24 fixed point number used as a multiplier to add or remove strength to
+ * the autogenerated bold variant. Use the DFB_EMBODLEN_FACTOR macro to convert a regular number to this format.
+ * The default value of 1.0 will be used unless DFDESC_EMBOLDEN is set (see DFBFontAttributes).
  */
 typedef struct {
      DFBFontDescriptionFlags            flags;
@@ -1174,10 +1180,13 @@ typedef struct {
      int                                outline_opacity;    /* Outline opacity as 16.16 fixed point integer */
 
      int                                rotation;
+
+     int                                embolden_factor;    /* Emboldening factor as 16.16 fixed point integer */
 } DFBFontDescription;
 
 #define DFB_DEGREES(deg) ((int)((deg)/360.0*(1<<24)))
 #define DFB_RADIANS(rad) ((int)((rad)/(2.0*M_PI)*(1<<24)))
+#define DFB_EMBOLDEN_FACTOR(factor) ((int)(factor*(1<<24)))
 
 /*
  * @internal
diff --git a/interfaces/IDirectFBFont/idirectfbfont_ft2.c b/interfaces/IDirectFBFont/idirectfbfont_ft2.c
index 3aacc35..f0ba68d 100644
--- a/interfaces/IDirectFBFont/idirectfbfont_ft2.c
+++ b/interfaces/IDirectFBFont/idirectfbfont_ft2.c
@@ -56,6 +56,9 @@
 
 #undef SIZEOF_LONG
 #include <ft2build.h>
+#include <freetype/ftsynth.h>
+#include <freetype/ftbitmap.h>
+#include <freetype/ftoutln.h>
 #include FT_GLYPH_H
 
 #ifndef FT_LOAD_TARGET_MONO
@@ -108,6 +111,8 @@ typedef struct {
      int          disable_charmap;
      int          fixed_advance;
      bool         fixed_clip;
+     bool         embolden;
+     int          embolden_factor;
      unsigned int indices[256];
 } FT2ImplData;
 
@@ -250,6 +255,83 @@ static const CoreFontEncodingFuncs ft2Latin1Funcs = {
 
 /**********************************************************************************************************************/
 
+static void ft2EmboldenGlyph(FT_GlyphSlot slot, float factor)
+{
+    // This code has been copied from ftsynth.c, following the recommendation in ftsynth.h. Multiplication by an user
+    // defined factor has been added.
+
+    FT_Library  library = slot->library;
+    FT_Face     face    = slot->face;
+    FT_Error    error;
+    FT_Pos      xstr, ystr;
+
+    if ( slot->format != FT_GLYPH_FORMAT_OUTLINE &&
+         slot->format != FT_GLYPH_FORMAT_BITMAP )
+      return;
+
+    /* some reasonable strength */
+    xstr = FT_MulFix( face->units_per_EM * factor,
+                      face->size->metrics.y_scale ) / 24;
+    ystr = xstr;
+
+    if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) {
+      /* ignore error */
+      (void)FT_Outline_Embolden( &slot->outline, xstr );
+
+      /* this is more than enough for most glyphs; if you need accurate */
+      /* values, you have to call FT_Outline_Get_CBox                   */
+      xstr = xstr * 2;
+      ystr = xstr;
+    }
+    else if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) {
+      /* round to full pixels */
+      xstr &= ~63;
+      if ( xstr == 0 )
+        xstr = 1 << 6;
+      ystr &= ~63;
+
+      /*
+       * XXX: overflow check for 16-bit system, for compatibility
+       *      with FT_GlyphSlot_Embolden() since freetype-2.1.10.
+       *      unfortunately, this function return no informations
+       *      about the cause of error.
+       */
+      if ( ( ystr >> 6 ) > FT_INT_MAX || ( ystr >> 6 ) < FT_INT_MIN )
+      {
+        //FT_TRACE1(( "FT_GlyphSlot_Embolden:" ));
+        //FT_TRACE1(( "too strong embolding parameter ystr=%d\n", ystr ));
+        return;
+      }
+      error = FT_GlyphSlot_Own_Bitmap( slot );
+      if ( error )
+        return;
+
+      error = FT_Bitmap_Embolden( library, &slot->bitmap, xstr, ystr );
+      if ( error )
+        return;
+    }
+
+    if ( slot->advance.x )
+      slot->advance.x += xstr;
+
+    if ( slot->advance.y )
+      slot->advance.y += ystr;
+
+    slot->metrics.width        += xstr;
+    slot->metrics.height       += ystr;
+    slot->metrics.horiBearingY += ystr;
+    slot->metrics.horiAdvance  += xstr;
+    slot->metrics.vertBearingX -= xstr / 2;
+    slot->metrics.vertBearingY += ystr;
+    slot->metrics.vertAdvance  += ystr;
+
+    /* XXX: 16-bit overflow case must be excluded before here */
+    if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
+      slot->bitmap_top += (FT_Int)( ystr >> 6 );
+}
+
+/**********************************************************************************************************************/
+
 static DFBResult
 render_glyph( CoreFont      *thiz,
               unsigned int   index,
@@ -277,6 +359,9 @@ render_glyph( CoreFont      *thiz,
           return DFB_FAILURE;
      }
 
+     if (data->embolden)
+         ft2EmboldenGlyph(face->glyph, (float)data->embolden_factor/(1<<24));
+
      pthread_mutex_unlock ( &library_mutex );
 
      err = dfb_surface_lock_buffer( surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock );
@@ -585,6 +670,9 @@ get_glyph_info( CoreFont      *thiz,
 
                return DFB_FAILURE;
           }
+
+        if (data->embolden)
+            ft2EmboldenGlyph(face->glyph, (float)data->embolden_factor/(1<<24));
      }
 
      pthread_mutex_unlock ( &library_mutex );
@@ -807,6 +895,7 @@ Construct( IDirectFBFont               *thiz,
      bool                disable_charmap = false;
      bool                disable_kerning = false;
      bool                load_mono = false;
+     bool                enable_embolden = false;
      u32                 mask = 0;
      const char         *filename = ctx->filename; /* intended for printf only */
 
@@ -901,6 +990,8 @@ Construct( IDirectFBFont               *thiz,
                disable_kerning = true;
           if (desc->attributes & DFFA_MONOCHROME)
                load_mono = true;
+          if (desc->attributes & DFFA_STYLE_SYNTH_BOLD)
+               enable_embolden = true;
      }
 
      if (load_mono)
@@ -1029,6 +1120,14 @@ Construct( IDirectFBFont               *thiz,
      data->face            = face;
      data->disable_charmap = disable_charmap;
 
+     data->embolden = enable_embolden;
+     desc->flags & DFDESC_EMBOLDEN ? data->embolden_factor = desc->embolden_factor : 1;
+
+     D_DEBUG( "DirectFB/FontFT2: emboldening: %d, factor: %d\n",
+             (desc->flags & DFDESC_EMBOLDEN) ? 1 : 0,
+             (desc->flags & DFDESC_EMBOLDEN) ? (float)data->embolden_factor/(1<<24) : 1 );
+
+
      if (FT_HAS_KERNING(face) && !disable_kerning)
           init_kerning_cache( (FT2ImplKerningData*) data, font->up_unit_x, font->up_unit_y);
 
-- 
1.7.1

_______________________________________________
directfb-dev mailing list
directfb-dev@directfb.org
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev

Reply via email to