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;
/**

