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: 1
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 2 guests