Cairo ignores fontconfig settings

Contribute code & patches
Forum rules
No support questions here please

Cairo ignores fontconfig settings

Postby grogi on Sat Jul 31, 2010 8:37 pm

I have mentioned before that Cairo does ignore Hintstyle property from Fontconfig. This is not the only one - switching subpixel rendering on/off, switching different lcdfilter weren't supported too. In general, the logic for merging the xrdb/Xft and Fontconfig settings was very convoluted..

I have created a comprehensive patch for Cairo 1.8.10 to address the mentioned issues and completely respect the Fontconfig. I tried to attach it to this post, but it .patch and .diff aren't allowed :(

Code: Select all
diff --combined src/cairo-ft-font.c
index 38b49c4,d0f769a..0000000
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@@ -1204,8 -1204,6 +1204,8 @@@ _render_glyph_outline (FT_Fac
      case CAIRO_ANTIALIAS_SUBPIXEL:
     switch (font_options->subpixel_order) {
         case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 +       case CAIRO_SUBPIXEL_ORDER_NONE:
 +                fprintf( stderr, "libCairo. WARN: Using subpixel antialiasing, but subpixel order is not defined.");
         case CAIRO_SUBPIXEL_ORDER_RGB:
         case CAIRO_SUBPIXEL_ORDER_BGR:
        render_mode = FT_RENDER_MODE_LCD;
@@@ -1521,9 -1519,9 +1521,9 @@@ static const cairo_unscaled_font_backen
  /* #cairo_ft_scaled_font_t */
 
  typedef struct _cairo_ft_scaled_font {
 -    cairo_scaled_font_t base;
 -    cairo_ft_unscaled_font_t *unscaled;
 -    cairo_ft_options_t ft_options;
 +   cairo_scaled_font_t base;
 +   cairo_ft_unscaled_font_t *unscaled;
 +   cairo_ft_options_t ft_options;
  } cairo_ft_scaled_font_t;
 
  const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
@@@ -1545,36 -1543,62 +1545,36 @@@ _get_pattern_ft_options (FcPattern *pat
      ft_options.load_flags = FT_LOAD_DEFAULT;
      ft_options.extra_flags = 0;
 
 -#ifndef FC_EMBEDDED_BITMAP
 -#define FC_EMBEDDED_BITMAP "embeddedbitmap"
 -#endif
 -
 -    /* Check whether to force use of embedded bitmaps */
 -    if (FcPatternGetBool (pattern,
 -           FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
 -   bitmap = FcFalse;
 -
 -    /* disable antialiasing if requested */
 -    if (FcPatternGetBool (pattern,
 -           FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
 -   antialias = FcTrue;
 -   
 -    if (antialias) {
 -   cairo_subpixel_order_t subpixel_order;
 -   int lcd_filter;
 -
 -   /* disable hinting if requested */
 -   if (FcPatternGetBool (pattern,
 -               FC_HINTING, 0, &hinting) != FcResultMatch)
 -       hinting = FcTrue;
 -
 -   if (FcPatternGetInteger (pattern,
 -             FC_RGBA, 0, &rgba) != FcResultMatch)
 -       rgba = FC_RGBA_UNKNOWN;
 +    int lcd_filter;
 
 +    if (FcPatternGetInteger (pattern, FC_RGBA, 0, &rgba) == FcResultMatch)
 +    {
     switch (rgba) {
 -   case FC_RGBA_RGB:
 -       subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
 -       break;
 -   case FC_RGBA_BGR:
 -       subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
 -       break;
 -   case FC_RGBA_VRGB:
 -       subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
 -       break;
 -   case FC_RGBA_VBGR:
 -       subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
 -       break;
 -   case FC_RGBA_UNKNOWN:
 -   case FC_RGBA_NONE:
 -   default:
 -       subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
 -       break;
 -   }
 -
 -   if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
 -       ft_options.base.subpixel_order = subpixel_order;
 -       ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 -   }
 +       case FC_RGBA_RGB:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
 +      break;
 +       case FC_RGBA_BGR:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
 +      break;
 +       case FC_RGBA_VRGB:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
 +      break;
 +       case FC_RGBA_VBGR:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
 +      break;
 +       case FC_RGBA_NONE:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_NONE;
 +      break;
 +       case FC_RGBA_UNKNOWN:
 +       default:
 +      ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
 +      break;
 +   }
 +    } // Fontconfig did not specify subpixel_order. Staying with SUBPIXEL_ORDER_DEAULT;
 
 -   if (FcPatternGetInteger (pattern,
 -             FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
 -   {
 -       switch (lcd_filter) {
 +    if (FcPatternGetInteger (pattern, FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
 +    {
 +   switch (lcd_filter) {
         case FC_LCD_NONE:
        ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
        break;
@@@ -1587,159 -1611,115 +1587,159 @@@
         case FC_LCD_LEGACY:
        ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
        break;
 -       }
     }
 +    } // No LCD_FILTER property in Fontconfig - falling back to CAIRO_LCD_FILTER_DEFAULT.
 
 -#ifdef FC_HINT_STYLE   
 -   if (FcPatternGetInteger (pattern,
 -             FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
 -       hintstyle = FC_HINT_FULL;
 -
 -   if (!hinting)
 -       hintstyle = FC_HINT_NONE;
 +    // Checking if antialias property was delivered from FontConfig
 +    if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) == FcResultMatch)
 +    {
 +   // Antialias is defined and is true
 +   if (antialias) {
 +       if ( (ft_options.base.subpixel_order!=CAIRO_SUBPIXEL_ORDER_NONE) ) {
 +      // Returned subpixel_order is defined and defines subpixel antialiasing or no subpixel_order information
 +      ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 +       } else {
 +      // Returned subpixel_order is defined and defines grayscale antialiasing
 +      ft_options.base.antialias = CAIRO_ANTIALIAS_GRAY;
 +       }
 +   } else {
 +       ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
 +   }
 +    } // Antialias not defined in Fontconfig. We are not doing anything - staying with CAIRO_ANTIALIAS_DEFAULT
 +
 +    // Processing hinting information
 +    // If FontConfig does provide FC_HINTING and it is false, we are not processing the FC_HINT_STYLE property - we assume hintnone
 +    // If Fontconfig does not provide FC_HINTING property, we are assuming it is true, so the FC_HINT_STYLE will be processed
 +    if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch)
 +   hinting = FcTrue;
 +
 +    // hinting is false only when Fontconfig verbosely set it to false.
 +    // in such case switching hint_style to CAIRO_HINT_STYLE_NONE
 +    if (!hinting) {
 +   ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
 +    }
 
 +#ifdef FC_HINT_STYLE   
 +    // Checking the FC_HINT_STYLE property only if hinting is true
 +    // If hinting is false, hinstyle is already set to CAIRO_HINT_STYLE_NONE
 +    if ( hinting && (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) == FcResultMatch)) {
     switch (hintstyle) {
 -   case FC_HINT_NONE:
 -       ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;   
 -       break;
 -   case FC_HINT_SLIGHT:
 -       ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
 -       break;
 -   case FC_HINT_MEDIUM:
 -   default:
 -       ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
 -       break;
 -   case FC_HINT_FULL:
 -       ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
 -       break;
 -   }
 -#else /* !FC_HINT_STYLE */
 -   if (!hinting) {
 -       ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
 +       case FC_HINT_NONE:
 +      ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;   
 +      break;
 +       case FC_HINT_SLIGHT:
 +      ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
 +      break;
 +       case FC_HINT_MEDIUM:
 +       default:
 +      ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
 +      break;
 +       case FC_HINT_FULL:
 +      ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
 +      break;
     }
 +    }
  #endif /* FC_HINT_STYLE */
 
 -   /* Force embedded bitmaps off if no hinting requested */
 -   if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
 -     bitmap = FcFalse;
 +#ifndef FC_EMBEDDED_BITMAP
 +#define FC_EMBEDDED_BITMAP "embeddedbitmap"
 +#endif
 +
 +    /* Check whether to force use of embedded bitmaps
 +     * If not verbosely requested, we are not forcing the bitmaps off */
 +    if (FcPatternGetBool (pattern, FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
 +   bitmap = FcTrue;
 
 -   if (!bitmap)
 -       ft_options.load_flags |= FT_LOAD_NO_BITMAP;
 +    /* Force embedded bitmaps off if no hinting requested */
 +    if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
 +   bitmap = FcFalse;
 
 -    } else {
 -   ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
 -    }
 +    if (!bitmap)
 +   ft_options.load_flags |= FT_LOAD_NO_BITMAP;
 
      /* force autohinting if requested */
 -    if (FcPatternGetBool (pattern,
 -           FC_AUTOHINT, 0, &autohint) != FcResultMatch)
 -   autohint = FcFalse;
 -
 -    if (autohint)
 -   ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
 +    if (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch) {   
 +   if (autohint)
 +       ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
 +    }
 
 -    if (FcPatternGetBool (pattern,
 -           FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
 -   vertical_layout = FcFalse;
 +    /* force vertical layout if requested */
 +    if (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT, 0, &vertical_layout) == FcResultMatch) {
 +   if (vertical_layout)
 +       ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
 +    }
 
  #ifndef FC_EMBOLDEN
  #define FC_EMBOLDEN "embolden"
  #endif
 -    if (FcPatternGetBool (pattern,
 -           FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
 -   embolden = FcFalse;
 -   
 -    if (embolden)
 -   ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
 +
 +    if (FcPatternGetBool (pattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch) {
 +   if (embolden)
 +       ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
 +    }
 
      *ret = ft_options;
  }
 
 +/**
 + * Merges the ft_options_t objects and saves the result in options object.
 + *
 + * @param other   - options returned by Fontconfig
 + * @param options - options read from xrdb/Xft. Merge result is saved here.
 + */
  static void
  _cairo_ft_options_merge (cairo_ft_options_t *options,
 -          cairo_ft_options_t *other)
 +                         cairo_ft_options_t *other)
  {
      int load_flags = other->load_flags;
      int load_target = FT_LOAD_TARGET_NORMAL;
 
      /* clear load target mode */
      load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
 -   
 +
      if (load_flags & FT_LOAD_NO_HINTING)
     other->base.hint_style = CAIRO_HINT_STYLE_NONE;
 
 -    if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
 -   options->base.antialias == CAIRO_ANTIALIAS_NONE) {
 -   options->base.antialias = CAIRO_ANTIALIAS_NONE;
 -   options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
 +    // If FontConfig returned a setting for subpixel_order, we are using it
 +    // It doesn't matter, what antialais we will have
 +    //    if antialias will be ANTIALIAS_NONE, the subpixel_order is ignored
 +    //    if antialias will be ANTIALIAS_GRAY or ANTIALIAS_SUBPIXEL,
 +    //       then it is taken into account detrmning type of antialias and during rendering
 +    if (other->base.subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
 +   options->base.subpixel_order = other->base.subpixel_order;
      }
 
 -    if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
 -   (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
 -    options->base.antialias == CAIRO_ANTIALIAS_GRAY)) {
 -   options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 -   options->base.subpixel_order = other->base.subpixel_order;
 +    // If Fontconfig returned setting for antialias, we are using it
 +    //    At this point it is important to switch AA on or off, if it was specified by Fontconfig.
 +    //    The type of antialias (ANTIALIAS_GRAY or ANTIALIAS_SUBPIXEL) is determined later.
 +    if (other->base.antialias != CAIRO_ANTIALIAS_DEFAULT) {
 +   options->base.antialias = other->base.antialias;
 +    }
 +
 +    // Checking if after the merge we are still using antialiasing
 +    // If so, we have to determine which kind - ANTIALIAS_GRAY or ANTIALIAS_SUBPIXEL
 +    if (options->base.antialias != CAIRO_ANTIALIAS_NONE) {
 +   switch (options->base.subpixel_order) {
 +       case (CAIRO_SUBPIXEL_ORDER_RGB) :
 +       case (CAIRO_SUBPIXEL_ORDER_BGR) :
 +       case (CAIRO_SUBPIXEL_ORDER_VRGB) :
 +       case (CAIRO_SUBPIXEL_ORDER_VBGR) :
 +      options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 +      break;
 +       case (CAIRO_SUBPIXEL_ORDER_DEFAULT) :
 +       case (CAIRO_SUBPIXEL_ORDER_NONE):
 +       default:
 +      options->base.antialias = CAIRO_ANTIALIAS_GRAY;
 +   }
      }
 
 -    if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
 +    if (other->base.hint_style != CAIRO_HINT_STYLE_DEFAULT)
     options->base.hint_style = other->base.hint_style;
 
 -    if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
 -   options->base.hint_style = CAIRO_HINT_STYLE_NONE;
 -
 -    if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
 +    if (other->base.lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
     options->base.lcd_filter = other->base.lcd_filter;
 
 -    if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
 -   options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
 -
 +    // Setting LoadFlags
      if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
     if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
         load_flags |= FT_LOAD_NO_HINTING;
@@@ -1748,30 -1728,30 +1748,30 @@@
     load_flags |= FT_LOAD_MONOCHROME;
      } else {
     switch (options->base.hint_style) {
 -   case CAIRO_HINT_STYLE_NONE:
 -       load_flags |= FT_LOAD_NO_HINTING;
 -       break;
 -   case CAIRO_HINT_STYLE_SLIGHT:
 -       load_target = FT_LOAD_TARGET_LIGHT;
 -       break;
 -   case CAIRO_HINT_STYLE_MEDIUM:
 -       break;
 -   case CAIRO_HINT_STYLE_FULL:
 -   case CAIRO_HINT_STYLE_DEFAULT:
 -       if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
 -      switch (options->base.subpixel_order) {
 -      case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 -      case CAIRO_SUBPIXEL_ORDER_RGB:
 -      case CAIRO_SUBPIXEL_ORDER_BGR:
 -          load_target = FT_LOAD_TARGET_LCD;
 -          break;
 -      case CAIRO_SUBPIXEL_ORDER_VRGB:
 -      case CAIRO_SUBPIXEL_ORDER_VBGR:
 -          load_target = FT_LOAD_TARGET_LCD_V;
 +       case CAIRO_HINT_STYLE_NONE:
 +      load_flags |= FT_LOAD_NO_HINTING;
 +      break;
 +       case CAIRO_HINT_STYLE_SLIGHT:
 +       case CAIRO_HINT_STYLE_MEDIUM:
 +      load_target = FT_LOAD_TARGET_LIGHT;
        break;
 +       case CAIRO_HINT_STYLE_FULL:
 +       case CAIRO_HINT_STYLE_DEFAULT:
 +      if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
 +          switch (options->base.subpixel_order) {
 +         case CAIRO_SUBPIXEL_ORDER_NONE:
 +         case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 +         case CAIRO_SUBPIXEL_ORDER_RGB:
 +         case CAIRO_SUBPIXEL_ORDER_BGR:
 +             load_target = FT_LOAD_TARGET_LCD;
 +             break;
 +         case CAIRO_SUBPIXEL_ORDER_VRGB:
 +         case CAIRO_SUBPIXEL_ORDER_VBGR:
 +             load_target = FT_LOAD_TARGET_LCD_V;
 +             break;
 +          }
        }
 -       }
 -       break;
 +      break;
     }
      }
 
diff --combined src/cairo-xlib-screen.c
index f5a3ae6,37e3418..0000000
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@@ -135,7 -135,6 +135,7 @@@ get_integer_default (Display    *dpy
  #ifndef FC_LCD_FILTER
  #define FC_LCD_FILTER   "lcdfilter"
  #endif
 +
  /* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
  #ifndef FC_LCD_NONE
  #define FC_LCD_NONE   0
@@@ -171,10 -170,7 +171,10 @@@ _cairo_xlib_init_screen_font_options (D
     xft_hinting = TRUE;
 
      if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
 -   xft_hintstyle = FC_HINT_FULL;
 +   /* -1 is an non-existant Fontconfig constant used to differentiate
 +    * the case when no hintstyle property is available.
 +    */
 +   xft_hintstyle = -1;
 
      if (!get_integer_default (dpy, "rgba", &xft_rgba))
      {
@@@ -246,10 -242,8 +246,10 @@@
      case FC_RGBA_VBGR:
     subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
     break;
 -    case FC_RGBA_UNKNOWN:
      case FC_RGBA_NONE:
 +   subpixel_order = CAIRO_SUBPIXEL_ORDER_NONE;
 +        break;
 +    case FC_RGBA_UNKNOWN:
      default:
     subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
      }
@@@ -273,14 -267,10 +273,14 @@@
      }
 
      if (xft_antialias) {
 -   if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
 +        switch (subpixel_order) {
 +        case CAIRO_SUBPIXEL_ORDER_DEFAULT:
 +        case CAIRO_SUBPIXEL_ORDER_NONE:
         antialias = CAIRO_ANTIALIAS_GRAY;
 -   else
 +            break;
 +        default:
         antialias = CAIRO_ANTIALIAS_SUBPIXEL;
 +        }
      } else {
     antialias = CAIRO_ANTIALIAS_NONE;
      }
diff --combined src/cairo.h
index a1cde78,cf4bc05..0000000
--- a/src/cairo.h
+++ b/src/cairo.h
@@@ -1032,7 -1032,6 +1032,7 @@@ typedef enum _cairo_font_weight
   *   with red at the top
   * @CAIRO_SUBPIXEL_ORDER_VBGR: Subpixel elements are arranged vertically
   *   with blue at the top
 + * @CAIRO_SUBPIXEL_ORDER_NONE: The screen does not have subpixel structure.
   *
   * The subpixel order specifies the order of color elements within
   * each pixel on the display device when rendering with an
@@@ -1043,8 -1042,7 +1043,8 @@@ typedef enum _cairo_subpixel_order
      CAIRO_SUBPIXEL_ORDER_RGB,
      CAIRO_SUBPIXEL_ORDER_BGR,
      CAIRO_SUBPIXEL_ORDER_VRGB,
 -    CAIRO_SUBPIXEL_ORDER_VBGR
 +    CAIRO_SUBPIXEL_ORDER_VBGR,
 +    CAIRO_SUBPIXEL_ORDER_NONE
  } cairo_subpixel_order_t;
    /**
grogi
Level 1
Level 1
 
Posts: 2
Joined: Sun Jul 25, 2010 8:35 pm

Linux Mint is funded by ads and donations.
 

Return to Code & Patches

Who is online

Users browsing this forum: No registered users and 1 guest