Submitted By:            Igor Živković <contact@igor-zivkovic.from.hr>
Date:                    2014-01-02
Initial Package Version: 1.12.16
Upstream Status:         Reported
Origin:                  https://bugs.freedesktop.org/show_bug.cgi?id=11838
Description:             Fixes inconsistent behavior on hintstyle and rgba settings.

diff -Naur cairo-1.12.16.orig/src/cairo-ft-font.c cairo-1.12.16/src/cairo-ft-font.c
--- cairo-1.12.16.orig/src/cairo-ft-font.c	2013-08-26 17:07:21.000000000 +0200
+++ cairo-1.12.16/src/cairo-ft-font.c	2014-01-02 22:39:02.604497815 +0100
@@ -1672,6 +1672,7 @@
 #ifdef FC_HINT_STYLE
     int hintstyle;
 #endif
+    int lcd_filter;
 
     _cairo_font_options_init_default (&ft_options.base);
     ft_options.load_flags = FT_LOAD_DEFAULT;
@@ -1681,81 +1682,125 @@
 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
 #endif
 
+#ifndef FcUndefined
+#define FcUndefined -1
+#endif
     /* Check whether to force use of embedded bitmaps */
     if (FcPatternGetBool (pattern,
 			  FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
-	bitmap = FcFalse;
+	bitmap = FcUndefined;
 
-    /* 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;
+    if (FcPatternGetInteger (pattern, 
+			     FC_RGBA, 0, &rgba) != FcResultMatch)
+	rgba = FC_RGBA_UNKNOWN;
+
+    /* Checking if antialias property was delivered from FontConfig */
+    if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
+    	antialias = FcUndefined;
+
+    /* 
+     * There are several cases of FontConfig setting we have to deal with
+     *   a) antialias == true, rgba == rgb/bgr/vrgb/vbgr      
+     *   b) antialias == true, rgba == none                   
+     *   c) antialias == true, rgba undefined                 
+     *   d) antialias == false                                
+     *   e) antialias == undefined, rgba == rgb/bgr/vrgb/vbgr  
+     *   f) antialias == undefined, rgba == none               
+     *   g) antialias == undefined, rgba undefined            
+     * 
+     * They are processed in following manner:
+     * a-c) antialias is defined and is true 
+     *   In such case we have to decide what type of antialias to select: GRAY or SUBPIXEL.
+     *   This is done based on the subpixel_order property.
+     *   - CAIRO_ANTIALIAS_GRAY when rgba is FC_RGBA_NONE
+     *   - CAIRO_ANTIALIAS_SUBPIXEL otherwise (if the rgba is rgb/bgr/vrgb/vbgr 
+     *     or subpixel wasn't defined in FC at all)
+     *
+     * d) antialias property is defined and is false
+     *   In such case we set the CAIRO_ANTIALIAS_NONE
+     *
+     * e-g) antialias property is not defined        
+     *   - the subpixel_order was specified in FC - very unlikely scenario, 
+     *     but in such case we are assuming antialiasing should be switched on.
+     *     Type of antialias is set it to CAIRO_ANTIALIAS_GRAY or CAIRO_ANTIALIAS_SUBPIXEL 
+     *     based on the rgba type.
+     *   - the subpixel_order was not specified as well - we are setting CAIRO_ANTIALIAS_DEFAULT
+     */
+    if ( (antialias == FcTrue) || 
+	 ( (antialias == FcUndefined) && (rgba != FC_RGBA_UNKNOWN) ) ) {
+        if (rgba == FC_RGBA_NONE) {
+            ft_options.base.antialias = CAIRO_ANTIALIAS_GRAY;
+	    ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+        } else {
+            ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
+	    /* ft_options.base.subpixel_order will be set later */
+        } 
+    } else if (antialias == FcFalse) {
+	ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
+	ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+    } /* Antialias property not defined in Fontconfig and rgba is not set.
+       * Not doing anything - staying with CAIRO_ANTIALIAS_DEFAULT */
 
+    if ( ft_options.base.antialias == CAIRO_ANTIALIAS_SUBPIXEL ) {
 	switch (rgba) {
 	case FC_RGBA_RGB:
-	    subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
+	    ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
 	    break;
 	case FC_RGBA_BGR:
-	    subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
+	    ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
 	    break;
 	case FC_RGBA_VRGB:
-	    subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
+	    ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
 	    break;
 	case FC_RGBA_VBGR:
-	    subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
+	    ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
 	    break;
 	case FC_RGBA_UNKNOWN:
 	case FC_RGBA_NONE:
 	default:
-	    subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+	    ft_options.base.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;
-	}
-
-	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;
-	    case FC_LCD_DEFAULT:
-		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
-		break;
-	    case FC_LCD_LIGHT:
-		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
-		break;
-	    case FC_LCD_LEGACY:
-		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
-		break;
-	    }
+    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;
+	case FC_LCD_DEFAULT:
+	    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
+	    break;
+	case FC_LCD_LIGHT:
+	    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
+	    break;
+	case FC_LCD_LEGACY:
+	    ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+	    break;
 	}
-
-#ifdef FC_HINT_STYLE
-	if (FcPatternGetInteger (pattern,
-				 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
-	    hintstyle = FC_HINT_FULL;
-
-	if (!hinting)
-	    hintstyle = FC_HINT_NONE;
-
+    } /* No LCD_FILTER property in FontConfig - staying with default CAIRO_LCD_FILTER_DEFAULT. */
+        
+    /* 
+     * Processing hinting information
+     * Hinting should be processed also when no antialias information delivered from FontConfig 
+     */
+    if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch)
+        hinting = FcUndefined;
+
+    /* 
+     * If hininng is forced off, setting CAIRO_HINT_STYLE_NONE
+     * If hinting is not forced off, processing hintstyle and setting appropiate style
+     * If hinting is not forced off nor hintstyle defined, 
+     *   staing with the default CAIRO_HINT_STYLE_DEFAUT
+     *   defined by _cairo_font_options_init_default
+     */
+    if (hinting == FcFalse) 
+        ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
+
+#ifdef FC_HINT_STYLE    
+    if ( (hinting != FcFalse) &&
+	 (FcPatternGetInteger (pattern, 
+			       FC_HINT_STYLE, 0, &hintstyle) == FcResultMatch) ) {
 	switch (hintstyle) {
 	case FC_HINT_NONE:
 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
@@ -1771,9 +1816,6 @@
 	    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;
 	}
 #endif /* FC_HINT_STYLE */
 
@@ -1781,26 +1823,22 @@
 	if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
 	  bitmap = FcFalse;
 
-	if (!bitmap)
-	    ft_options.load_flags |= FT_LOAD_NO_BITMAP;
-
-    } else {
-	ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
-    }
+	if (bitmap == FcFalse)
+		ft_options.load_flags |= FT_LOAD_NO_BITMAP;
 
     /* force autohinting if requested */
     if (FcPatternGetBool (pattern,
 			  FC_AUTOHINT, 0, &autohint) != FcResultMatch)
-	autohint = FcFalse;
+	autohint = FcUndefined;
 
-    if (autohint)
+    if (autohint == FcTrue)
 	ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
 
     if (FcPatternGetBool (pattern,
 			  FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
-	vertical_layout = FcFalse;
+	vertical_layout = FcUndefined;
 
-    if (vertical_layout)
+    if (vertical_layout == FcTrue)
 	ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
 
 #ifndef FC_EMBOLDEN
@@ -1808,9 +1846,9 @@
 #endif
     if (FcPatternGetBool (pattern,
 			  FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
-	embolden = FcFalse;
+	embolden = FcUndefined;
 
-    if (embolden)
+    if (embolden == FcTrue)
 	ft_options.synth_flags |= CAIRO_FT_SYNTHESIZE_BOLD;
 
     *ret = ft_options;
@@ -1830,31 +1868,38 @@
     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 (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 others structure defines settings for antialiasing, we are processing them */
+    if (other->base.antialias != CAIRO_ANTIALIAS_DEFAULT) {
+	if ( other->base.antialias == CAIRO_ANTIALIAS_NONE ) {
+	    /* Force antialias off */
+	    options->base.antialias = CAIRO_ANTIALIAS_NONE;
+	    options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+	} else { 
+	    /* Force antialias on */
+
+	    /* If antialias==CAIRO_ANTIALIAS_SUBPIXEL is set, 
+	     * but the subpixel_order is set to CAIRO_SUBPIXEL_ORDER_DEFAULT, 
+	     * we have to determine what type of antialiasing will be used based
+	     * on current subpixel order */	    
+	    if ( (other->base.subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT) &&
+	         (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) ) {
+		if (options->base.subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT) 
+		    options->base.antialias = CAIRO_ANTIALIAS_GRAY;
+		else
+		    options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
+	    } else {
+		options->base.subpixel_order = other->base.subpixel_order;
+		options->base.antialias = other->base.antialias;
+	    }
+	}
     }
-
-    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;
-
     if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
 	if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
 	    load_flags |= FT_LOAD_NO_HINTING;
