diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index c5fb728..28ab05f 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,15 @@ 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; - 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,65 +1253,71 @@ #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; - if (!bitmap && antialias) - ft_options.load_flags |= FT_LOAD_NO_BITMAP; - else if (!antialias) - ft_options.load_flags |= FT_LOAD_MONOCHROME; + if (FcPatternGetInteger (pattern, + FC_RGBA, 0, &rgba) != FcResultMatch) + rgba = FC_RGBA_UNKNOWN; - /* disable hinting if requested */ - if (FcPatternGetBool (pattern, - FC_HINTING, 0, &hinting) != FcResultMatch) - hinting = FcTrue; + switch (rgba) { + 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_UNKNOWN: + case FC_RGBA_NONE: + default: + break; + } -#ifdef FC_HINT_STYLE - if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) - hintstyle = FC_HINT_FULL; +#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.base.hint_style = CAIRO_HINT_STYLE_NONE; + break; case FC_HINT_SLIGHT: - case FC_HINT_MEDIUM: - target_flags = 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; + 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 { -#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.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 { + ft_options.base.antialias = CAIRO_ANTIALIAS_NONE; } - ft_options.load_flags |= target_flags; - /* force autohinting if requested */ if (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint) != FcResultMatch) @@ -1325,71 +1332,88 @@ #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; } -static int -_get_options_load_flags (const cairo_font_options_t *options) +static void +_cairo_ft_options_merge (cairo_ft_options_t *options, + cairo_ft_options_t *other) { - int load_flags = 0; + int load_flags = other->load_flags; + int load_target = FT_LOAD_TARGET_NORMAL; - /* disable antialiasing if requested */ - switch (options->antialias) { - case CAIRO_ANTIALIAS_NONE: -#ifdef FT_LOAD_TARGET_MONO - load_flags |= FT_LOAD_TARGET_MONO; -#endif - load_flags |= FT_LOAD_MONOCHROME; - 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; - break; - case CAIRO_SUBPIXEL_ORDER_VRGB: - case CAIRO_SUBPIXEL_ORDER_VBGR: - load_flags |= FT_LOAD_TARGET_LCD_V; - break; - } - /* fall through ... */ - case CAIRO_ANTIALIAS_DEFAULT: - case CAIRO_ANTIALIAS_GRAY: - load_flags |= FT_LOAD_NO_BITMAP; - break; + /* clear load target mode */ + load_flags &= ~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 (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; } - /* disable hinting if requested */ - switch (options->hint_style) { + if (options->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; + + 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: - load_flags |= FT_LOAD_TARGET_LIGHT; - break; + if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { + load_target = FT_LOAD_TARGET_MONO; + load_flags |= FT_LOAD_MONOCHROME; + } + break; case CAIRO_HINT_STYLE_FULL: - default: - load_flags |= FT_LOAD_TARGET_NORMAL; - break; + case CAIRO_HINT_STYLE_DEFAULT: + if (options->base.antialias == CAIRO_ANTIALIAS_NONE) { + load_target = FT_LOAD_TARGET_MONO; + load_flags |= FT_LOAD_MONOCHROME; + } else 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; + break; + } + } + break; } - return load_flags; + options->load_flags = load_flags | load_target; + options->extra_flags = other->extra_flags; } static cairo_scaled_font_t * @@ -1421,7 +1445,8 @@ _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; + _cairo_font_options_init_copy (&scaled_font->ft_options.base, options); + _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options); _cairo_scaled_font_init (&scaled_font->base, font_face, @@ -1888,10 +1913,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 +1953,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; @@ -2072,8 +2097,6 @@ _cairo_ft_font_face_scaled_font_create ( */ ft_options = font_face->ft_options; - if (font_face->unscaled->from_face) - ft_options.load_flags |= _get_options_load_flags (options); *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled, &font_face->base, @@ -2306,6 +2329,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);