[poppler] poppler/CairoFontEngine.cc

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Wed Apr 9 11:09:07 PDT 2008


 poppler/CairoFontEngine.cc |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

New commits:
commit 42db4890e8295aaec5a1be12d1414fc0a9048550
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Mar 27 10:52:22 2008 +0000

    Do not call FT_Done_Face on a live cairo_font_face_t.
    
    Currently CairoFont calls FT_Done_Face on its deletion, but the FT_Face
    is usually still in use within cairo. This causes a failure later when
    cairo tries to create a glyph from its cairo_font_face_t.
    
    From http://bugs.freedesktop.org/show_bug.cgi?id=15216:
    ==13745== Invalid read of size 4
    ==13745==    at 0x51BE572: FT_Load_Glyph (ftobjs.c:549)
    ==13745==    by 0x4A24921: _cairo_ft_scaled_glyph_init (cairo-ft-font.c:1922)
    ==13745==    by 0x4A117AB: _cairo_scaled_glyph_lookup
    (cairo-scaled-font.c:1674)
    ==13745==    by 0x4A12A5A: _cairo_scaled_font_glyph_device_extents
    (cairo-scaled-font.c:1124)
    ==13745==    by 0x4A21ECD: _cairo_analysis_surface_show_glyphs
    (cairo-analysis-surface.c:516)
    ==13745==    by 0x4A144DC: _cairo_surface_show_glyphs (cairo-surface.c:2086)
    ==13745==    by 0x4A1FCC8: _cairo_meta_surface_replay_internal
    (cairo-meta-surface.c:816)
    ==13745==    by 0x4A214B1: _paint_page (cairo-paginated-surface.c:299)
    ==13745==    by 0x4A2171E: _cairo_paginated_surface_show_page
    (cairo-paginated-surface.c:445)
    ==13745==    by 0x4A14BDF: cairo_surface_show_page (cairo-surface.c:1702)
    ==13745==    by 0x49FF661: cairo_show_page (cairo.c:2155)
    ==13745==    by 0xA267D97:
    pdf_document_file_exporter_end_page(_EvFileExporter*) (ev-poppler.cc:1753)
    ==13745==  Address 0x55c5630 is 88 bytes inside a block of size 552 free'd
    ==13745==    at 0x402269C: free (vg_replace_malloc.c:326)
    ==13745==    by 0x51B7ABC: ft_free (ftsystem.c:158)
    ==13745==    by 0x51BB319: ft_mem_free (ftutil.c:171)
    ==13745==    by 0x51BC318: destroy_face (ftobjs.c:856)
    ==13745==    by 0x51BC3B2: FT_Done_Face (ftobjs.c:1972)
    ==13745==    by 0x4363704: CairoFont::~CairoFont() (CairoFontEngine.cc:251)
    ==13745==    by 0x436401D: CairoFontEngine::getFont(GfxFont*, XRef*)
    (CairoFontEngine.cc:335)
    ==13745==    by 0x4366915: CairoOutputDev::updateFont(GfxState*)
    (CairoOutputDev.cc:318)
    ==13745==    by 0x5093BF1: Gfx::opShowText(Object*, int) (Gfx.cc:3073)
    ==13745==    by 0x508F901: Gfx::execOp(Object*, Object*, int) (Gfx.cc:726)
    ==13745==    by 0x50906FF: Gfx::go(int) (Gfx.cc:594)
    ==13745==    by 0x5090C96: Gfx::display(Object*, int) (Gfx.cc:557)
    
    The solution is to release the reference to the cairo_font_face_t upon
    destruction of the CairoFont, and then to release the FT_Face from the
    destroy notify of the cairo_font_face_t.

diff --git a/poppler/CairoFontEngine.cc b/poppler/CairoFontEngine.cc
index 67034f0..5073252 100644
--- a/poppler/CairoFontEngine.cc
+++ b/poppler/CairoFontEngine.cc
@@ -31,11 +31,10 @@ static void fileWrite(void *stream, char *data, int len) {
 // CairoFont
 //------------------------------------------------------------------------
 
-static void cairo_font_face_destroy (void *data)
+static void _ft_done_face (void *data)
 {
-  CairoFont *font = (CairoFont *) data;
-
-  delete font;
+  FT_Face face = (FT_Face) data;
+  FT_Done_Face (face);
 }
 
 CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool useCIDs) {
@@ -224,16 +223,16 @@ CairoFont *CairoFont::create(GfxFont *gfxFont, XRef *xref, FT_Library lib, GBool
   cairo_font_face = cairo_ft_font_face_create_for_ft_face (face,
 							   FT_LOAD_NO_HINTING |
 							   FT_LOAD_NO_BITMAP);
-  if (cairo_font_face == NULL) {
-    error(-1, "could not create cairo font\n");
+  if (cairo_font_face_status (cairo_font_face)) {
+    error(-1, "could not create cairo font: %s\n", cairo_status_to_string (cairo_font_face_status (cairo_font_face)));
     goto err2; /* this doesn't do anything, but it looks like we're
 		* handling the error */
   } {
   CairoFont *ret = new CairoFont(ref, cairo_font_face, face, codeToGID, codeToGIDLen, substitute);
-  cairo_font_face_set_user_data (cairo_font_face, 
+  cairo_font_face_set_user_data (cairo_font_face,
 				 &cairo_font_face_key,
-				 ret,
-				 cairo_font_face_destroy);
+				 face,
+				 _ft_done_face);
 
   return ret;
   }
@@ -249,7 +248,7 @@ CairoFont::CairoFont(Ref ref, cairo_font_face_t *cairo_font_face, FT_Face face,
 					    codeToGIDLen(codeToGIDLen), substitute(substitute) { }
 
 CairoFont::~CairoFont() {
-  FT_Done_Face (face);
+  cairo_font_face_destroy (cairo_font_face);
   gfree(codeToGID);
 }
 


More information about the poppler mailing list