diff --git a/ROADMAP b/ROADMAP diff --git a/configure.in b/configure.in diff --git a/doc/public/.gitignore b/doc/public/.gitignore diff --git a/doc/public/Makefile.am b/doc/public/Makefile.am diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml diff --git a/doc/public/cairo-overrides.txt b/doc/public/cairo-overrides.txt diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt diff --git a/doc/public/cairo.types b/doc/public/cairo.types diff --git a/doc/public/language-bindings.xml b/doc/public/language-bindings.xml diff --git a/doc/public/tmpl/.gitignore b/doc/public/tmpl/.gitignore diff --git a/doc/public/tmpl/cairo-atsui.sgml b/doc/public/tmpl/cairo-atsui.sgml diff --git a/doc/public/tmpl/cairo-beos.sgml b/doc/public/tmpl/cairo-beos.sgml diff --git a/doc/public/tmpl/cairo-font-options.sgml b/doc/public/tmpl/cairo-font-options.sgml diff --git a/doc/public/tmpl/cairo-font.sgml b/doc/public/tmpl/cairo-font.sgml diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml diff --git a/doc/public/tmpl/cairo-glitz.sgml b/doc/public/tmpl/cairo-glitz.sgml diff --git a/doc/public/tmpl/cairo-image.sgml b/doc/public/tmpl/cairo-image.sgml diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml diff --git a/doc/public/tmpl/cairo-pattern.sgml b/doc/public/tmpl/cairo-pattern.sgml diff --git a/doc/public/tmpl/cairo-pdf.sgml b/doc/public/tmpl/cairo-pdf.sgml diff --git a/doc/public/tmpl/cairo-png.sgml b/doc/public/tmpl/cairo-png.sgml diff --git a/doc/public/tmpl/cairo-ps.sgml b/doc/public/tmpl/cairo-ps.sgml diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml diff --git a/doc/public/tmpl/cairo-scaled-font.sgml b/doc/public/tmpl/cairo-scaled-font.sgml diff --git a/doc/public/tmpl/cairo-status.sgml b/doc/public/tmpl/cairo-status.sgml diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml diff --git a/doc/public/tmpl/cairo-svg.sgml b/doc/public/tmpl/cairo-svg.sgml diff --git a/doc/public/tmpl/cairo-text.sgml b/doc/public/tmpl/cairo-text.sgml diff --git a/doc/public/tmpl/cairo-transforms.sgml b/doc/public/tmpl/cairo-transforms.sgml diff --git a/doc/public/tmpl/cairo-types.sgml b/doc/public/tmpl/cairo-types.sgml diff --git a/doc/public/tmpl/cairo-version.sgml b/doc/public/tmpl/cairo-version.sgml diff --git a/doc/public/tmpl/cairo-win32-fonts.sgml b/doc/public/tmpl/cairo-win32-fonts.sgml diff --git a/doc/public/tmpl/cairo-win32.sgml b/doc/public/tmpl/cairo-win32.sgml diff --git a/doc/public/tmpl/cairo-xcb-xrender.sgml b/doc/public/tmpl/cairo-xcb-xrender.sgml diff --git a/doc/public/tmpl/cairo-xcb.sgml b/doc/public/tmpl/cairo-xcb.sgml diff --git a/doc/public/tmpl/cairo-xlib-xrender.sgml b/doc/public/tmpl/cairo-xlib-xrender.sgml diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml diff --git a/doc/public/version.xml.in b/doc/public/version.xml.in diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c diff --git a/pixman/src/icimage.c b/pixman/src/icimage.c diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index d48cec7..9353977 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -96,12 +96,16 @@ struct _cairo_ft_unscaled_font { double x_scale; /* Extracted X scale factor */ double y_scale; /* Extracted Y scale factor */ cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/ + cairo_matrix_t current_shape; int lock; /* count of how many times this font has been locked */ cairo_ft_font_face_t *faces; /* Linked list of faces for this font */ }; +static cairo_user_data_key_t +_cairo_ft_font_face_options_key; + static int _cairo_ft_unscaled_font_keys_equal (const void *key_a, const void *key_b); @@ -119,10 +123,16 @@ typedef struct _cairo_ft_options { cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */ } cairo_ft_options_t; +typedef struct _cairo_fc_ft_options { + cairo_font_options_t base; + cairo_ft_options_t ft_options; +} cairo_fc_ft_options_t; + struct _cairo_ft_font_face { cairo_font_face_t base; cairo_ft_unscaled_font_t *unscaled; cairo_ft_options_t ft_options; + cairo_font_options_t font_options; cairo_ft_font_face_t *next; }; @@ -391,7 +401,7 @@ _cairo_ft_unscaled_font_create_for_patte if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch) goto UNWIND; filename = (char *) fc_filename; - + if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch) goto UNWIND; @@ -618,7 +628,12 @@ _cairo_ft_unscaled_font_set_scale (cairo unscaled->x_scale = sf.x_scale; unscaled->y_scale = sf.y_scale; - + + cairo_matrix_init (&unscaled->current_shape, + sf.shape[0][0], sf.shape[0][1], + sf.shape[1][0], sf.shape[1][1], + 0.0, 0.0); + mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]); mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]); mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]); @@ -897,6 +912,17 @@ _get_bitmap_surface (FT_Bitmap *bi return CAIRO_STATUS_SUCCESS; } +static cairo_bool_t +_cairo_ft_glyph_embolden (FT_GlyphSlot glyph) +{ +#if HAVE_FT_GLYPHSLOT_EMBOLDEN + FT_GlyphSlot_Embolden (glyph); + return TRUE; +#else + return FALSE; +#endif +} + /* Converts an outline FT_GlyphSlot into an image * * This could go through _render_glyph_bitmap as well, letting @@ -915,17 +941,20 @@ _get_bitmap_surface (FT_Bitmap *bi static cairo_status_t _render_glyph_outline (FT_Face face, cairo_font_options_t *font_options, + cairo_bool_t vert_layout, + cairo_bool_t lazy_embolden, cairo_image_surface_t **surface) { FT_GlyphSlot glyphslot = face->glyph; FT_Outline *outline = &glyphslot->outline; - FT_Bitmap bitmap; + FT_Bitmap bitmap, * target = &bitmap; FT_BBox cbox; FT_Matrix matrix; int hmul = 1; int vmul = 1; unsigned int width, height, stride; cairo_bool_t subpixel = FALSE; + cairo_bool_t owner = TRUE; cairo_status_t status; FT_Outline_Get_CBox (outline, &cbox); @@ -1016,17 +1045,35 @@ _render_glyph_outline (FT_Face return CAIRO_STATUS_NO_MEMORY; } - status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); + if (lazy_embolden) { + glyphslot->bitmap = bitmap; + glyphslot->format = FT_GLYPH_FORMAT_BITMAP; + + if (_cairo_ft_glyph_embolden (glyphslot) && + glyphslot->bitmap.buffer != bitmap.buffer) { + owner = FALSE; + target = &glyphslot->bitmap; + + free (bitmap.buffer); + } else { + glyphslot->bitmap.buffer = NULL; + } + } + status = _get_bitmap_surface (target, owner, font_options, surface); if (status) return status; } /* * Note: the font's coordinate system is upside down from ours, so the - * Y coordinate of the control box needs to be negated. + * Y coordinate of the control box needs to be negated. Vertical glyphs + * are centred. */ - (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0); + if (vert_layout) + (*surface)->base.device_x_offset = floor (-(double) bitmap.width / 2.0); + else + (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0); (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0); return CAIRO_STATUS_SUCCESS; @@ -1082,18 +1129,17 @@ _render_glyph_bitmap (FT_Face fac return status; } -#if 0 -/* XXX */ static cairo_status_t -_transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) +_transform_glyph_bitmap (cairo_matrix_t * shape, + cairo_image_surface_t ** surface) { - cairo_ft_font_transform_t sf; cairo_matrix_t original_to_transformed; cairo_matrix_t transformed_to_original; cairo_image_surface_t *old_image; cairo_surface_t *image; double x[4], y[4]; double origin_x, origin_y; + int origin_width, origin_height; int i; int x_min, y_min, x_max, y_max; int width, height; @@ -1101,26 +1147,26 @@ _transform_glyph_bitmap (cairo_image_gly cairo_surface_pattern_t pattern; /* We want to compute a transform that takes the origin - * (val->size.x, val->size.y) to 0,0, then applies the "shape" - * portion of the font transform + * (x, y) to 0.0, then applies the "shape" portion of + * the font transform */ - _compute_transform (&sf, &val->key.scale); - - cairo_matrix_init (&original_to_transformed, - sf.shape[0][0], sf.shape[0][1], - sf.shape[1][0], sf.shape[1][1], - 0, 0); + original_to_transformed = *shape; + + origin_x = (*surface)->base.device_x_offset; + origin_y = (*surface)->base.device_y_offset; + origin_width = cairo_image_surface_get_width (&(*surface)->base); + origin_height = cairo_image_surface_get_height (&(*surface)->base); cairo_matrix_translate (&original_to_transformed, - val->size.x, val->size.y); + origin_x, origin_y); /* Find the bounding box of the original bitmap under that * transform */ - x[0] = 0; y[0] = 0; - x[1] = val->size.width; y[1] = 0; - x[2] = val->size.width; y[2] = val->size.height; - x[3] = 0; y[3] = val->size.height; + x[0] = 0; y[0] = 0; + x[1] = origin_width; y[1] = 0; + x[2] = origin_width; y[2] = origin_height; + x[3] = 0; y[3] = origin_height; for (i = 0; i < 4; i++) cairo_matrix_transform_point (&original_to_transformed, @@ -1183,11 +1229,11 @@ _transform_glyph_bitmap (cairo_image_gly _cairo_pattern_fini (&pattern.base); - /* Now update the cache entry for the new bitmap, recomputing + /* Now update the glyph for the new bitmap, recomputing * the origin based on the final transform. */ - origin_x = - val->size.x; - origin_y = - val->size.y; + origin_x = - origin_x; + origin_y = - origin_y; cairo_matrix_transform_point (&original_to_transformed, &origin_x, &origin_y); @@ -1195,14 +1241,11 @@ _transform_glyph_bitmap (cairo_image_gly (*surface) = (cairo_image_surface_t *)image; cairo_surface_destroy (&old_image->base); - val->size.width = width; - val->size.height = height; - val->size.x = - floor (origin_x + 0.5); - val->size.y = - floor (origin_y + 0.5); - + (*surface)->base.device_x_offset = - floor (origin_x + 0.5); + (*surface)->base.device_y_offset = - floor (origin_y + 0.5); + return status; } -#endif static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { _cairo_ft_unscaled_font_destroy, @@ -1216,6 +1259,7 @@ #endif typedef struct _cairo_ft_scaled_font { cairo_scaled_font_t base; cairo_ft_unscaled_font_t *unscaled; + cairo_font_options_t font_options; cairo_ft_options_t ft_options; } cairo_ft_scaled_font_t; @@ -1227,30 +1271,21 @@ 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 transform; - FcMatrix *font_matrix; + FcBool antialias, vertical_layout, hinting, autohint, bitmap, global_advance; cairo_ft_options_t ft_options; int rgba; -#ifdef FC_HINT_STYLE +#ifdef FC_HINT_STYLE int hintstyle; -#endif +#endif int target_flags = 0; - ft_options.load_flags = 0; + ft_options.load_flags = FT_LOAD_DEFAULT; ft_options.extra_flags = 0; #ifndef FC_EMBEDDED_BITMAP #define FC_EMBEDDED_BITMAP "embeddedbitmap" #endif - - if (FcPatternGetMatrix (pattern, - FC_MATRIX, 0, &font_matrix) != FcResultMatch) - font_matrix = NULL; - - transform = (font_matrix && (font_matrix->xx != 1 || font_matrix->xy != 0 || - font_matrix->yx != 0 || font_matrix->yy != 1)); - + /* Check whether to force use of embedded bitmaps */ if (FcPatternGetBool (pattern, FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch) @@ -1261,61 +1296,64 @@ #endif FC_ANTIALIAS, 0, &antialias) != FcResultMatch) antialias = FcTrue; - if ((!bitmap && antialias) || transform) + 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 (antialias) { - switch (hintstyle) { - case FC_HINT_SLIGHT: - case FC_HINT_MEDIUM: - target_flags = FT_LOAD_TARGET_LIGHT; - break; - default: - target_flags = FT_LOAD_TARGET_NORMAL; - 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; -#endif /* FC_FHINT_STYLE */ - if (FcPatternGetInteger (pattern, - FC_RGBA, 0, &rgba) != FcResultMatch) - rgba = FC_RGBA_UNKNOWN; +#ifdef FC_HINT_STYLE + if (FcPatternGetInteger (pattern, + FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) + hintstyle = FC_HINT_FULL; +#else + target_flags = FT_LOAD_NO_HINTING; +#endif - 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; + if (antialias) { + if (FcPatternGetInteger (pattern, + FC_RGBA, 0, &rgba) != FcResultMatch) + rgba = FC_RGBA_UNKNOWN; + + switch (rgba) { + 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; + case FC_RGBA_UNKNOWN: + case FC_RGBA_NONE: + default: +#ifdef FC_HINT_STYLE + if (hinting) { + switch (hintstyle) { + case FC_HINT_SLIGHT: + case FC_HINT_MEDIUM: + target_flags |= FT_LOAD_TARGET_LIGHT; + break; + default: + target_flags |= FT_LOAD_TARGET_NORMAL; + break; + } + } +#endif + break; + } } +#ifdef FT_LOAD_TARGET_MONO + else + target_flags |= FT_LOAD_TARGET_MONO; +#endif ft_options.load_flags |= target_flags; @@ -1326,6 +1364,8 @@ #endif /* FC_FHINT_STYLE */ if (autohint) ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT; + else + ft_options.load_flags |= FT_LOAD_NO_AUTOHINT; if (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch) @@ -1333,7 +1373,14 @@ #endif /* FC_FHINT_STYLE */ if (vertical_layout) ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT; + + if (FcPatternGetBool (pattern, + FC_GLOBAL_ADVANCE, 0, &global_advance) != FcResultMatch) + global_advance = FcTrue; + if (!global_advance) + ft_options.load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; + #ifdef FC_EMBOLDEN { FcBool embolden; @@ -1350,6 +1397,84 @@ #endif return ft_options; } +static void +_cairo_ft_font_pattern_to_font_options (FcPattern *pattern, + cairo_font_options_t *options) +{ + FcBool antialias, hinting; + int rgba; +#ifdef FC_HINT_STYLE + int hintstyle; +#endif + + options->antialias = CAIRO_ANTIALIAS_DEFAULT; + options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT; + options->hint_style = CAIRO_HINT_STYLE_DEFAULT; + options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; + + /* disable antialiasing if requested */ + if (FcPatternGetBool (pattern, + FC_ANTIALIAS, 0, &antialias) != FcResultMatch) + antialias = FcTrue; + + /* disable hinting if requested */ + if (FcPatternGetBool (pattern, + FC_HINTING, 0, &hinting) != FcResultMatch) + hinting = FcTrue; + + if (!hinting) + options->hint_style = CAIRO_HINT_STYLE_NONE; + +#ifdef FC_HINT_STYLE + if (FcPatternGetInteger (pattern, + FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch) + hintstyle = FC_HINT_FULL; +#else + options->hinting = CAIRO_HINT_STYLE_NONE; +#endif + + if (FcPatternGetInteger (pattern, + FC_RGBA, 0, &rgba) != FcResultMatch) + rgba = FC_RGBA_UNKNOWN; + +#ifdef FC_HINT_STYLE + switch (hintstyle) { + case FC_HINT_SLIGHT: + options->hint_style = CAIRO_HINT_STYLE_SLIGHT; + break; + case FC_HINT_MEDIUM: + options->hint_style = CAIRO_HINT_STYLE_MEDIUM; + break; + case FC_HINT_FULL: + default: + options->hint_style = CAIRO_HINT_STYLE_FULL; + break; + } +#endif + + if ((rgba != FC_RGBA_UNKNOWN && rgba != FC_RGBA_NONE) && antialias) { + options->antialias = CAIRO_ANTIALIAS_SUBPIXEL; + switch (rgba) { + case FC_RGBA_RGB: + options->subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; + break; + case FC_RGBA_BGR: + options->subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; + break; + case FC_RGBA_VRGB: + options->subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; + break; + case FC_RGBA_VBGR: + options->subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; + break; + } + } +#ifdef FT_LOAD_TARGET_MONO + if (!antialias) + options->antialias = CAIRO_ANTIALIAS_NONE; +#endif +} + static int _get_options_load_flags (const cairo_font_options_t *options) { @@ -1379,24 +1504,23 @@ #endif case CAIRO_ANTIALIAS_DEFAULT: case CAIRO_ANTIALIAS_GRAY: load_flags |= FT_LOAD_NO_BITMAP; + /* disable hinting if requested */ + switch (options->hint_style) { + case CAIRO_HINT_STYLE_NONE: + load_flags |= FT_LOAD_NO_HINTING; + break; + case CAIRO_HINT_STYLE_SLIGHT: + case CAIRO_HINT_STYLE_MEDIUM: + load_flags |= FT_LOAD_TARGET_LIGHT; + break; + case CAIRO_HINT_STYLE_FULL: + default: + load_flags |= FT_LOAD_TARGET_NORMAL; + break; + } break; } - /* disable hinting if requested */ - switch (options->hint_style) { - case CAIRO_HINT_STYLE_NONE: - load_flags |= FT_LOAD_NO_HINTING; - break; - case CAIRO_HINT_STYLE_SLIGHT: - case CAIRO_HINT_STYLE_MEDIUM: - load_flags |= FT_LOAD_TARGET_LIGHT; - break; - case CAIRO_HINT_STYLE_FULL: - default: - load_flags |= FT_LOAD_TARGET_NORMAL; - break; - } - return load_flags; } @@ -1411,6 +1535,7 @@ _cairo_ft_scaled_font_create (cairo_ft_u cairo_ft_scaled_font_t *scaled_font = NULL; FT_Face face; FT_Size_Metrics *metrics; + cairo_font_options_t *font_options; cairo_font_extents_t fs_metrics; face = _cairo_ft_unscaled_font_lock_face (unscaled); @@ -1439,6 +1564,13 @@ _cairo_ft_scaled_font_create (cairo_ft_u _cairo_ft_unscaled_font_set_scale (unscaled, &scaled_font->base.scale); + scaled_font->font_options = scaled_font->base.options; + font_options = cairo_font_face_get_user_data (font_face, + &_cairo_ft_font_face_options_key); + if (font_options) + cairo_font_options_merge (&scaled_font->font_options, + font_options); + metrics = &face->size->metrics; /* @@ -1473,7 +1605,7 @@ _cairo_ft_scaled_font_create (cairo_ft_u /* FIXME: this doesn't do vertical layout atm. */ - fs_metrics.max_y_advance = 0.0; + fs_metrics.max_y_advance = fs_metrics.height; _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics); @@ -1502,6 +1634,7 @@ _cairo_ft_scaled_font_create_toy (cairo_ cairo_matrix_t scale; cairo_ft_font_transform_t sf; cairo_ft_options_t ft_options; + cairo_font_options_t *ft_font_options; unsigned char *family = (unsigned char*) toy_face->family; pattern = FcPatternCreate (); @@ -1558,6 +1691,20 @@ _cairo_ft_scaled_font_create_toy (cairo_ goto FREE_RESOLVED; ft_options = _get_pattern_ft_options (resolved); + ft_font_options = cairo_font_face_get_user_data (&toy_face->base, + &_cairo_ft_font_face_options_key); + + if (!ft_font_options) { + ft_font_options = cairo_font_options_create (); + + if (font_options) { + _cairo_ft_font_pattern_to_font_options (pattern, ft_font_options); + cairo_font_face_set_user_data (&toy_face->base, + &_cairo_ft_font_face_options_key, + ft_font_options, + (cairo_destroy_func_t)cairo_font_options_destroy); + } + } new_font = _cairo_ft_scaled_font_create (unscaled, &toy_face->base, @@ -1725,6 +1872,9 @@ _cairo_ft_scaled_glyph_init (void *abs cairo_text_extents_t fs_metrics; cairo_ft_scaled_font_t *scaled_font = abstract_font; cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + cairo_bool_t embolden = FALSE; + cairo_bool_t lazy_embolden = FALSE; + cairo_bool_t vertical_layout = FALSE; FT_GlyphSlot glyph; FT_Face face; FT_Error error; @@ -1736,10 +1886,17 @@ _cairo_ft_scaled_glyph_init (void *abs if (!face) return CAIRO_STATUS_NO_MEMORY; - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0) + if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && + (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)) load_flags |= FT_LOAD_NO_BITMAP; - + + if (load_flags & FT_LOAD_VERTICAL_LAYOUT) + vertical_layout = TRUE; + + if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) + embolden = TRUE; + + error = FT_Load_Glyph (scaled_font->unscaled->face, _cairo_scaled_glyph_index(scaled_glyph), load_flags); @@ -1750,16 +1907,10 @@ _cairo_ft_scaled_glyph_init (void *abs } glyph = face->glyph; - -#if HAVE_FT_GLYPHSLOT_EMBOLDEN - /* - * embolden glyphs if requested - */ - if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) - FT_GlyphSlot_Embolden (glyph); -#endif if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { + if (embolden) + _cairo_ft_glyph_embolden (glyph); /* * Compute font-space metrics */ @@ -1793,34 +1944,56 @@ #endif FT_Pos y1, y2; FT_Pos advance; - x1 = (metrics->horiBearingX) & -64; - x2 = (metrics->horiBearingX + metrics->width + 63) & -64; - y1 = (-metrics->horiBearingY) & -64; - y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; - - advance = ((metrics->horiAdvance + 32) & -64); - - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; - - fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; - - /* - * use untransformed advance values - * XXX uses horizontal advance only at present; should provide FT_LOAD_VERTICAL_LAYOUT - */ - fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; - fs_metrics.y_advance = 0; + if (!vertical_layout) { + x1 = (metrics->horiBearingX) & -64; + x2 = (metrics->horiBearingX + metrics->width + 63) & -64; + y1 = (-metrics->horiBearingY) & -64; + y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; + + advance = ((metrics->horiAdvance + 32) & -64); + + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + + fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; + fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + + fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; + fs_metrics.y_advance = 0; + } else { + x1 = (metrics->vertBearingX) & -64; + x2 = (metrics->vertBearingX + metrics->width + 63) & -64; + y1 = (-metrics->vertBearingY) & -64; + y2 = (-metrics->vertBearingY + metrics->height + 63) & -64; + + advance = ((metrics->vertAdvance + 32) & -64); + + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + + fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; + fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + + fs_metrics.x_advance = 0; + fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor; + } } else { - fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; - fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; - - fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; - fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; - - fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; - fs_metrics.y_advance = 0 * y_factor; + fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; + fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; + + if (!vertical_layout) { + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; + + fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; + fs_metrics.y_advance = 0 * y_factor; + } else { + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->vertBearingY) * y_factor; + + fs_metrics.x_advance = 0 * x_factor; + fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor; + } } _cairo_scaled_glyph_set_metrics (scaled_glyph, @@ -1831,12 +2004,37 @@ #endif if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { cairo_image_surface_t *surface; cairo_status_t status; + + if (embolden && + scaled_font->font_options.antialias == CAIRO_ANTIALIAS_NONE && + glyph->format == FT_GLYPH_FORMAT_OUTLINE && + (load_flags & FT_LOAD_NO_HINTING) == 0) + lazy_embolden = TRUE; + + if (lazy_embolden && (info & CAIRO_SCALED_GLYPH_INFO_METRICS)) { + error = FT_Load_Glyph (face, + _cairo_scaled_glyph_index(scaled_glyph), + load_flags); + + if (error) { + cairo_ft_scaled_font_unlock_face (abstract_font); + return CAIRO_STATUS_NO_MEMORY; + } + } + + if (embolden && !lazy_embolden) + _cairo_ft_glyph_embolden (glyph); + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - status = _render_glyph_outline (face, &scaled_font->base.options, - &surface); - else - status = _render_glyph_bitmap (face, &scaled_font->base.options, + status = _render_glyph_outline (face, &scaled_font->font_options, + vertical_layout, lazy_embolden, &surface); + else { + status = _render_glyph_bitmap (face, &scaled_font->font_options, &surface); + if (!status && unscaled->have_shape) + status = _transform_glyph_bitmap (&unscaled->current_shape, + &surface); + } if (status) { cairo_ft_scaled_font_unlock_face (abstract_font); return status; @@ -1863,9 +2061,13 @@ #endif cairo_ft_scaled_font_unlock_face (abstract_font); return CAIRO_STATUS_NO_MEMORY; } + + if (embolden) + _cairo_ft_glyph_embolden (glyph); } + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) - status = _decompose_glyph_outline (face, &scaled_font->base.options, + status = _decompose_glyph_outline (face, &scaled_font->font_options, &path); else status = CAIRO_STATUS_NO_MEMORY; @@ -2130,8 +2332,7 @@ cairo_ft_font_options_substitute (const #ifdef FC_HINT_STYLE if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) { - int hint_style; - + int hint_style = 0; switch (options->hint_style) { case CAIRO_HINT_STYLE_SLIGHT: hint_style = FC_HINT_SLIGHT; @@ -2182,6 +2383,7 @@ cairo_ft_font_face_create_for_pattern (F { cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; + cairo_font_options_t * font_options; unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern); if (unscaled == NULL) { @@ -2193,12 +2395,28 @@ cairo_ft_font_face_create_for_pattern (F _get_pattern_ft_options (pattern)); _cairo_unscaled_font_destroy (&unscaled->base); - if (font_face) - return font_face; - else { - _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; + if (!font_face) + goto error; + + font_options = cairo_font_face_get_user_data (font_face, + &_cairo_ft_font_face_options_key); + + if (!font_options) { + font_options = cairo_font_options_create (); + + if (font_options) { + _cairo_ft_font_pattern_to_font_options (pattern, font_options); + cairo_font_face_set_user_data (font_face, + &_cairo_ft_font_face_options_key, + font_options, + (cairo_destroy_func_t)cairo_font_options_destroy); + } } + + return font_face; + error: + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_font_face_t *)&_cairo_font_face_nil; } /** diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index e881157..7e70a4b 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -1180,6 +1180,8 @@ _cairo_glitz_surface_composite_trapezoid } _cairo_glitz_surface_set_image (mask, image, 0, 0); + + cairo_surface_destroy (&image->base); } _cairo_glitz_surface_set_attributes (src, &attributes); diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 7fae110..1a26454 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -2074,40 +2074,90 @@ cairo_xlib_surface_get_depth (cairo_surf return surface->depth; } -typedef struct _cairo_xlib_surface_font_private { - Display *dpy; +#define GLYPH_INFO_MAX (3) +typedef struct _cairo_xlib_font_glyph_info { GlyphSet glyphset; - cairo_format_t format; - XRenderPictFormat *xrender_format; + XRenderPictFormat *format; +} cairo_xlib_font_glyph_info_t; + +typedef struct _cairo_xlib_surface_font_private { + Display *dpy; + cairo_xlib_font_glyph_info_t glyph_info[GLYPH_INFO_MAX]; + int num_formats; } cairo_xlib_surface_font_private_t; static cairo_status_t _cairo_xlib_surface_font_init (Display *dpy, - cairo_scaled_font_t *scaled_font, - cairo_format_t format) + cairo_scaled_font_t *scaled_font) { cairo_xlib_surface_font_private_t *font_private; + int i; font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); if (!font_private) return CAIRO_STATUS_NO_MEMORY; font_private->dpy = dpy; - font_private->format = format; - font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format); - font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format); + + font_private->num_formats = 0; + for (i = 0; i < GLYPH_INFO_MAX; i ++) { + font_private->glyph_info[i].format = NULL; + font_private->glyph_info[i].glyphset = None; + } + scaled_font->surface_private = font_private; scaled_font->surface_backend = &cairo_xlib_surface_backend; return CAIRO_STATUS_SUCCESS; } +static cairo_xlib_font_glyph_info_t * +_cairo_xlib_surface_font_get_glyph_info (cairo_scaled_font_t *scaled_font, + cairo_format_t format) +{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + cairo_xlib_font_glyph_info_t *glyph_info = &font_private->glyph_info[0]; + int foffset; + + switch (format) { + case CAIRO_FORMAT_A1: + foffset = 0; + break; + case CAIRO_FORMAT_A8: + foffset = 1; + break; + case CAIRO_FORMAT_ARGB32: + foffset = 2; + break; + case CAIRO_FORMAT_RGB24: + default: + ASSERT_NOT_REACHED; + } + + if (glyph_info[foffset].glyphset == None) { + glyph_info[foffset].format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(font_private->dpy, + format); + glyph_info[foffset].glyphset = XRenderCreateGlyphSet (font_private->dpy, + glyph_info[foffset].format); + font_private->num_formats ++; + } + + return glyph_info + foffset; +} + static void _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) { cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; if (font_private) { - XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset); + int i; + + for (i = 0; i < GLYPH_INFO_MAX; i ++) { + if (font_private->glyph_info[i].glyphset) + XRenderFreeGlyphSet (font_private->dpy, + font_private->glyph_info[i].glyphset); + } + free (font_private); } } @@ -2120,8 +2170,10 @@ _cairo_xlib_surface_scaled_glyph_fini (c if (font_private != NULL && scaled_glyph->surface_private != NULL) { unsigned long glyph_index = _cairo_scaled_glyph_index(scaled_glyph); + cairo_xlib_font_glyph_info_t *glyph_info = scaled_glyph->surface_private; + XRenderFreeGlyphs (font_private->dpy, - font_private->glyphset, + glyph_info->glyphset, &glyph_index, 1); } } @@ -2144,41 +2196,22 @@ _cairo_xlib_surface_add_glyph (Display * unsigned char *data; cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_xlib_surface_font_private_t *font_private; + cairo_xlib_font_glyph_info_t * cairo_glyph_info; cairo_image_surface_t *glyph_surface = scaled_glyph->surface; if (scaled_font->surface_private == NULL) { - status = _cairo_xlib_surface_font_init (dpy, scaled_font, - glyph_surface->format); + status = _cairo_xlib_surface_font_init (dpy, scaled_font); if (status) return status; } font_private = scaled_font->surface_private; - /* If the glyph format does not match the font format, then we - * create a temporary surface for the glyph image with the font's - * format. - */ - if (glyph_surface->format != font_private->format) { - cairo_t *cr; - cairo_surface_t *tmp_surface; - - tmp_surface = cairo_image_surface_create (font_private->format, - glyph_surface->width, - glyph_surface->height); - cr = cairo_create (tmp_surface); - cairo_set_source_surface (cr, &glyph_surface->base, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - - status = cairo_status (cr); - - cairo_destroy (cr); - - glyph_surface = (cairo_image_surface_t *) tmp_surface; - - if (status) - goto BAIL; - } + cairo_glyph_info = _cairo_xlib_surface_font_get_glyph_info (scaled_font, + glyph_surface->format); + if (cairo_glyph_info->glyphset == None) + return CAIRO_STATUS_NO_MEMORY; + + scaled_glyph->surface_private = cairo_glyph_info; /* * Most of the font rendering system thinks of glyph tiles as having @@ -2288,18 +2321,14 @@ _cairo_xlib_surface_add_glyph (Display * glyph_index = _cairo_scaled_glyph_index (scaled_glyph); - XRenderAddGlyphs (dpy, font_private->glyphset, + XRenderAddGlyphs (dpy, cairo_glyph_info->glyphset, &glyph_index, &(glyph_info), 1, (char *) data, glyph_surface->stride * glyph_surface->height); if (data != glyph_surface->data) free (data); - - BAIL: - if (glyph_surface != scaled_glyph->surface) - cairo_surface_destroy (&glyph_surface->base); - + BAIL: return status; } @@ -2313,9 +2342,9 @@ _cairo_xlib_surface_old_show_glyphs8 (c int source_x, int source_y, const cairo_glyph_t *glyphs, - int num_glyphs) + int num_glyphs, + cairo_xlib_font_glyph_info_t *glyph_info) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; XGlyphElt8 *elts = NULL; XGlyphElt8 stack_elts [N_STACK_BUF]; @@ -2343,7 +2372,7 @@ _cairo_xlib_surface_old_show_glyphs8 (c chars[i] = glyphs[i].index; elts[i].chars = &(chars[i]); elts[i].nchars = 1; - elts[i].glyphset = font_private->glyphset; + elts[i].glyphset = glyph_info->glyphset; thisX = (int) floor (glyphs[i].x + 0.5); thisY = (int) floor (glyphs[i].y + 0.5); elts[i].xOff = thisX - lastX; @@ -2356,7 +2385,7 @@ _cairo_xlib_surface_old_show_glyphs8 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->xrender_format, + glyph_info->format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2375,9 +2404,9 @@ _cairo_xlib_surface_old_show_glyphs16 (c int source_x, int source_y, const cairo_glyph_t *glyphs, - int num_glyphs) + int num_glyphs, + cairo_xlib_font_glyph_info_t *glyph_info) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; XGlyphElt16 *elts = NULL; XGlyphElt16 stack_elts [N_STACK_BUF]; @@ -2405,7 +2434,7 @@ _cairo_xlib_surface_old_show_glyphs16 (c chars[i] = glyphs[i].index; elts[i].chars = &(chars[i]); elts[i].nchars = 1; - elts[i].glyphset = font_private->glyphset; + elts[i].glyphset = glyph_info->glyphset; thisX = (int) floor (glyphs[i].x + 0.5); thisY = (int) floor (glyphs[i].y + 0.5); elts[i].xOff = thisX - lastX; @@ -2418,7 +2447,7 @@ _cairo_xlib_surface_old_show_glyphs16 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->xrender_format, + glyph_info->format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2437,9 +2466,9 @@ _cairo_xlib_surface_old_show_glyphs32 (c int source_x, int source_y, const cairo_glyph_t *glyphs, - int num_glyphs) + int num_glyphs, + cairo_xlib_font_glyph_info_t *glyph_info) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; XGlyphElt32 *elts = NULL; XGlyphElt32 stack_elts [N_STACK_BUF]; @@ -2467,7 +2496,7 @@ _cairo_xlib_surface_old_show_glyphs32 (c chars[i] = glyphs[i].index; elts[i].chars = &(chars[i]); elts[i].nchars = 1; - elts[i].glyphset = font_private->glyphset; + elts[i].glyphset = glyph_info->glyphset; thisX = (int) floor (glyphs[i].x + 0.5); thisY = (int) floor (glyphs[i].y + 0.5); elts[i].xOff = thisX - lastX; @@ -2480,7 +2509,7 @@ _cairo_xlib_surface_old_show_glyphs32 (c _render_operator (op), src->src_picture, self->dst_picture, - font_private->xrender_format, + glyph_info->format, source_x + elts[0].xOff, source_y + elts[0].yOff, 0, 0, elts, num_glyphs); @@ -2513,8 +2542,10 @@ _cairo_xlib_surface_old_show_glyphs (cai int glyphs_remaining, chunk_size, max_chunk_size; composite_operation_t operation; cairo_scaled_glyph_t *scaled_glyph; + cairo_xlib_font_glyph_info_t **glyphs_info, **glyphs_info_chunk; + cairo_xlib_font_glyph_info_t *stack_glyphs_info[N_STACK_BUF]; cairo_xlib_surface_font_private_t *font_private; - int i; + int i, boundary; unsigned long max_index = 0; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format) @@ -2547,6 +2578,15 @@ _cairo_xlib_surface_old_show_glyphs (cai if (status) goto FAIL; + if (num_glyphs < N_STACK_BUF) + glyphs_info = stack_glyphs_info; + else + glyphs_info = malloc (sizeof(cairo_xlib_font_glyph_info_t *) * num_glyphs); + if (!glyphs_info) { + status = CAIRO_STATUS_NO_MEMORY; + goto FAIL; + } + /* Send all unsent glyphs to the server */ for (i = 0; i < num_glyphs; i++) { if (glyphs[i].index > max_index) @@ -2556,11 +2596,11 @@ _cairo_xlib_surface_old_show_glyphs (cai CAIRO_SCALED_GLYPH_INFO_SURFACE, &scaled_glyph); if (status != CAIRO_STATUS_SUCCESS) - return status; + goto FAIL1; if (scaled_glyph->surface_private == NULL) { _cairo_xlib_surface_add_glyph (self->dpy, scaled_font, scaled_glyph); - scaled_glyph->surface_private = (void *) 1; } + glyphs_info[i] = (cairo_xlib_font_glyph_info_t *)scaled_glyph->surface_private; } _cairo_xlib_surface_ensure_dst_picture (self); @@ -2574,28 +2614,38 @@ _cairo_xlib_surface_old_show_glyphs (cai max_chunk_size -= sz_xRenderCompositeGlyphs32Req; max_chunk_size /= sz_xGlyphElt; - for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs; - glyphs_remaining; - glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size) + font_private = scaled_font->surface_private; + + for (glyphs_remaining = num_glyphs, glyphs_chunk = glyphs, + glyphs_info_chunk = glyphs_info; glyphs_remaining; + glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size, + glyphs_info_chunk += chunk_size) { chunk_size = MIN (glyphs_remaining, max_chunk_size); - + if (font_private->num_formats > 1 && chunk_size > 1) { + for (boundary = 1; boundary < chunk_size; boundary ++) { + if (glyphs_info_chunk[boundary - 1]->glyphset != glyphs_info_chunk[boundary]->glyphset) { + chunk_size = boundary; + break; + } + } + } /* Call the appropriate sub-function. */ if (max_index < 256) status = _cairo_xlib_surface_old_show_glyphs8 (scaled_font, op, src, self, source_x + attributes.x_offset - dest_x, source_y + attributes.y_offset - dest_y, - glyphs_chunk, chunk_size); + glyphs_chunk, chunk_size, glyphs_info_chunk[0]); else if (max_index < 65536) status = _cairo_xlib_surface_old_show_glyphs16 (scaled_font, op, src, self, source_x + attributes.x_offset - dest_x, source_y + attributes.y_offset - dest_y, - glyphs_chunk, chunk_size); + glyphs_chunk, chunk_size, glyphs_info_chunk[0]); else status = _cairo_xlib_surface_old_show_glyphs32 (scaled_font, op, src, self, source_x + attributes.x_offset - dest_x, source_y + attributes.y_offset - dest_y, - glyphs_chunk, chunk_size); + glyphs_chunk, chunk_size, glyphs_info_chunk[0]); if (status != CAIRO_STATUS_SUCCESS) break; } @@ -2615,6 +2665,11 @@ _cairo_xlib_surface_old_show_glyphs (cai dest_x, dest_y, width, height); } + + FAIL1: + if (glyphs_info != stack_glyphs_info) + free (glyphs_info); + FAIL: _cairo_pattern_release_surface (pattern, &src->base, &attributes); diff --git a/test/select-font-face-pdf-argb32-ref.png b/test/select-font-face-pdf-argb32-ref.png Binary files a/test/select-font-face-pdf-argb32-ref.png and b/test/select-font-face-pdf-argb32-ref.png differ