index c5fb728..e284057 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -116,6 +116,7 @@ typedef enum _cairo_ft_extra_flags { } cairo_ft_extra_flags_t; typedef struct _cairo_ft_options { + cairo_font_options_t base; int load_flags; /* flags for FT_Load_Glyph */ cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */ } cairo_ft_options_t; @@ -1228,15 +1229,16 @@ const cairo_scaled_font_backend_t cairo_ static cairo_ft_options_t _get_pattern_ft_options (FcPattern *pattern) { - FcBool antialias, vertical_layout, hinting, autohint, bitmap; + FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden; cairo_ft_options_t ft_options; int rgba; #ifdef FC_HINT_STYLE int hintstyle; #endif - int target_flags = 0; + int load_target = FT_LOAD_TARGET_NORMAL; - ft_options.load_flags = 0; + _cairo_font_options_init_default (&ft_options.base); + ft_options.load_flags = FT_LOAD_DEFAULT; ft_options.extra_flags = 0; #ifndef FC_EMBEDDED_BITMAP @@ -1252,64 +1254,82 @@ #endif if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch) antialias = FcTrue; + + if (antialias) { + if (!bitmap) + ft_options.load_flags |= FT_LOAD_NO_BITMAP; + + /* disable hinting if requested */ + if (FcPatternGetBool (pattern, + FC_HINTING, 0, &hinting) != FcResultMatch) + hinting = FcTrue; + +#ifdef FC_HINT_STYLE + if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) + hintstyle = FC_HINT_FULL; - if (!bitmap && antialias) - ft_options.load_flags |= FT_LOAD_NO_BITMAP; - else if (!antialias) - ft_options.load_flags |= FT_LOAD_MONOCHROME; - - /* disable hinting if requested */ - if (FcPatternGetBool (pattern, - FC_HINTING, 0, &hinting) != FcResultMatch) - hinting = FcTrue; - -#ifdef FC_HINT_STYLE - if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) - hintstyle = FC_HINT_FULL; - - if (!hinting || hintstyle == FC_HINT_NONE) - ft_options.load_flags |= FT_LOAD_NO_HINTING; + if (!hinting) + hintstyle = FC_HINT_NONE; - if (antialias) { switch (hintstyle) { + case FC_HINT_NONE: + ft_options.load_flags |= FT_LOAD_NO_HINTING; + ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; + break; case FC_HINT_SLIGHT: - case FC_HINT_MEDIUM: - target_flags = FT_LOAD_TARGET_LIGHT; + load_target = FT_LOAD_TARGET_LIGHT; + ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT; break; + case FC_HINT_MEDIUM: default: - target_flags = FT_LOAD_TARGET_NORMAL; + load_target = FT_LOAD_TARGET_NORMAL; + ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM; + break; + case FC_HINT_FULL: + if (FcPatternGetInteger (pattern, + FC_RGBA, 0, &rgba) != FcResultMatch) + rgba = FC_RGBA_UNKNOWN; + switch (rgba) { + case FC_RGBA_RGB: + ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; + load_target = FT_LOAD_TARGET_LCD; + break; + case FC_RGBA_BGR: + ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; + load_target = FT_LOAD_TARGET_LCD; + break; + case FC_RGBA_VRGB: + ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; + load_target = FT_LOAD_TARGET_LCD_V; + break; + case FC_RGBA_VBGR: + ft_options.base.subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; + load_target = FT_LOAD_TARGET_LCD_V; + break; + case FC_RGBA_UNKNOWN: + case FC_RGBA_NONE: + default: + break; + } + ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL; break; } - } else { -#ifdef FT_LOAD_TARGET_MONO - target_flags = FT_LOAD_TARGET_MONO; -#endif - } #else /* !FC_HINT_STYLE */ - if (!hinting) - target_flags = FT_LOAD_NO_HINTING; + if (!hinting) { + ft_options.load_flags |= FT_LOAD_NO_HINTING; + ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE; + } #endif /* FC_FHINT_STYLE */ - - if (FcPatternGetInteger (pattern, - FC_RGBA, 0, &rgba) != FcResultMatch) - rgba = FC_RGBA_UNKNOWN; - - switch (rgba) { - case FC_RGBA_UNKNOWN: - case FC_RGBA_NONE: - default: - break; - case FC_RGBA_RGB: - case FC_RGBA_BGR: - target_flags = FT_LOAD_TARGET_LCD; - break; - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: - target_flags = FT_LOAD_TARGET_LCD_V; - break; + } else { + /* + * for monochrome rendering, we force hinting and rendering, + * ignoring the pattern values for hint style. + */ + ft_options.load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO; + ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; } - ft_options.load_flags |= target_flags; + ft_options.load_flags |= load_target; /* force autohinting if requested */ if (FcPatternGetBool (pattern, @@ -1326,18 +1346,15 @@ #endif /* FC_FHINT_STYLE */ if (vertical_layout) ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT; -#ifdef FC_EMBOLDEN - { - FcBool embolden; - - if (FcPatternGetBool (pattern, - FC_EMBOLDEN, 0, &embolden) != FcResultMatch) - embolden = FcFalse; - - if (embolden) - ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN; - } +#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; return ft_options; } @@ -1345,33 +1362,36 @@ #endif static int _get_options_load_flags (const cairo_font_options_t *options) { - int load_flags = 0; + int load_flags = FT_LOAD_DEFAULT; + int load_target = FT_LOAD_TARGET_NORMAL; + int render_flags = FT_RENDER_MODE_NORMAL; /* disable antialiasing if requested */ switch (options->antialias) { case CAIRO_ANTIALIAS_NONE: #ifdef FT_LOAD_TARGET_MONO - load_flags |= FT_LOAD_TARGET_MONO; + load_target = FT_LOAD_TARGET_MONO; #endif - load_flags |= FT_LOAD_MONOCHROME; + load_flags |= FT_LOAD_MONOCHROME; + render_flags = FT_RENDER_MODE_MONO; break; case CAIRO_ANTIALIAS_SUBPIXEL: switch (options->subpixel_order) { case CAIRO_SUBPIXEL_ORDER_DEFAULT: case CAIRO_SUBPIXEL_ORDER_RGB: case CAIRO_SUBPIXEL_ORDER_BGR: - load_flags |= FT_LOAD_TARGET_LCD; + render_flags |= FT_RENDER_MODE_LCD; break; case CAIRO_SUBPIXEL_ORDER_VRGB: case CAIRO_SUBPIXEL_ORDER_VBGR: - load_flags |= FT_LOAD_TARGET_LCD_V; + render_flags |= FT_RENDER_MODE_LCD_V; break; } - /* fall through ... */ - case CAIRO_ANTIALIAS_DEFAULT: case CAIRO_ANTIALIAS_GRAY: load_flags |= FT_LOAD_NO_BITMAP; break; + case CAIRO_ANTIALIAS_DEFAULT: + break; } /* disable hinting if requested */ @@ -1381,15 +1401,19 @@ #endif break; case CAIRO_HINT_STYLE_SLIGHT: case CAIRO_HINT_STYLE_MEDIUM: - load_flags |= FT_LOAD_TARGET_LIGHT; + /* slight/medium hinting - except for monochrome rendering */ + if (render_flags != FT_RENDER_MODE_MONO) + load_target |= FT_LOAD_TARGET_LIGHT; break; case CAIRO_HINT_STYLE_FULL: default: - load_flags |= FT_LOAD_TARGET_NORMAL; + if (render_flags == FT_RENDER_MODE_LCD) + load_target = FT_LOAD_TARGET_LCD; + else if (render_flags == FT_RENDER_MODE_LCD_V) + load_target = FT_LOAD_TARGET_LCD_V; break; } - - return load_flags; + return load_flags | load_target; } static cairo_scaled_font_t * @@ -1421,7 +1445,11 @@ _cairo_ft_scaled_font_create (cairo_ft_u if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; - scaled_font->ft_options = ft_options; + scaled_font->ft_options.load_flags = ft_options.load_flags; + scaled_font->ft_options.extra_flags = ft_options.extra_flags; + _cairo_font_options_init_copy (&scaled_font->ft_options.base, options); + cairo_font_options_merge (&scaled_font->ft_options.base, + &ft_options.base); _cairo_scaled_font_init (&scaled_font->base, font_face, @@ -1888,10 +1916,10 @@ #endif cairo_status_t status; if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - status = _render_glyph_outline (face, &scaled_font->base.options, + status = _render_glyph_outline (face, &scaled_font->ft_options.base, &surface); } else { - status = _render_glyph_bitmap (face, &scaled_font->base.options, + status = _render_glyph_bitmap (face, &scaled_font->ft_options.base, &surface); if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) status = _transform_glyph_bitmap (&unscaled->current_shape, @@ -1928,7 +1956,7 @@ #endif } if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - status = _decompose_glyph_outline (face, &scaled_font->base.options, + status = _decompose_glyph_outline (face, &scaled_font->ft_options.base, &path); else status = CAIRO_INT_STATUS_UNSUPPORTED; @@ -2306,6 +2334,7 @@ cairo_ft_font_face_create_for_ft_face (F ft_options.load_flags = load_flags; ft_options.extra_flags = 0; + _cairo_font_options_init_default (&ft_options.base); font_face = _cairo_ft_font_face_create (unscaled, ft_options); _cairo_unscaled_font_destroy (&unscaled->base);