Bug 28145

Summary: cairo_font_face_finish()
Product: cairo Reporter: Chris Wilson <chris>
Component: freetype font backendAssignee: David Turner <david>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: blocker    
Priority: medium CC: britten, carlosgc, freedesktop
Version: 1.9.7   
Hardware: All   
OS: All   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 68382    

Description Chris Wilson 2010-05-17 08:55:06 UTC
The user needs to notify cairo when they have deleted the underlying resource so that cairo can drop all associated caches and handles.

When creating an ft_font_face() from an FT_Face we key on (long)FT_Face, and so it is possible for a new FT_Face to have the same key if the original face is destroyed and Cairo remains blissfully unaware.
Comment 1 Ian Britten 2010-05-17 11:08:29 UTC
Just to clarify for anyone reading this:
I ran into this problem using a [cairomm] workflow similar to this:

// Do a bunch of sequential draws
for (int i=0; i<numDraws; ++i)
{
        // Make a new surface+context
        Cairo::RefPtr<Cairo::ImageSurface> surface =
                Cairo::ImageSurface::create( ... );
        Cairo::RefPtr<Cairo::Context> context =
                Cairo::Context::create(surface);

        // Make a new FT face
        FT_Face *ftFace = FT_Open_Face( "/path/to/ttf" ... );

        // Draw a bunch of different text using the same FT face
        for (j=0; j<numText; ++j)
        {
                Cairo::RefPtr<Cairo::FontFace> cFace =
                        Cairo::FtFontFace::create(ftFace, FT_LOAD_NO_HINTING);

                // set misc attributes, such as size, colour, etc.

                // Draw some text
                context.set_font_face(cFace);
                context.show_glyphs( ... );
        }

        // Finish with the Cairo entities
        surface->write_to_png( ... );
        surface->finish();
        context.clear();  // Discard
        surface.clear();  // Discard

        // Discard the (one) FT face we allocated
        FT_Done_Face(ftFace);
}

This workflow fails to render the text if the pointer address of the
FT_Face matches that of one used (and freed) during a previous iteration.
As alluded to by Chris, the crux of the problem seems to be Cairo using
a single static cache of FT_Face objects, without accounting for the
possibility that the face has been freed, then another one allocated
with the same pointer address.

[ Maybe the cache should be on the Surface/Context, rather than global,
and thus cleaned up with each Surface/Context?  Just a thought ... ]
Comment 2 Behdad Esfahbod 2010-05-17 11:35:42 UTC
The root of the problem is that FT_Face() is not ref-counted.
Maybe someone can fix that...  It's been proposed upstream already.
Comment 3 Chris Wilson 2010-05-17 11:52:02 UTC
In this particular case, yes, it would eliminate the problem if FT_Face was refcounted. However, the other objects that cairo implements such as cairo_t and cairo_surface_t, do provide a cairo_*_finish() function so that the user can dispose of any internal references to the object prior to destroying the underlying resource. I feel we should be consistent in our API and implement finish() for all objects, which would not only provide a means to workaround FT_Face, but also similar issues that may arise with other font backends - such as user fonts.
Comment 4 Behdad Esfahbod 2010-05-17 11:56:56 UTC
Agreed that cairo_font_face_finish() is useful and should be there.

What about cairo_scaled_font_finish()?  It would simply release the font-face associated with the scaled font.
Comment 5 Adrian Johnson 2010-05-17 15:42:36 UTC
What happens if cairo_font_face_finish() is called before cairo_surface_finish() on a font that a PS/PDF surface is holding?
Comment 6 Behdad Esfahbod 2010-05-17 18:52:19 UTC
(In reply to comment #5)
> What happens if cairo_font_face_finish() is called before
> cairo_surface_finish() on a font that a PS/PDF surface is holding?

The surface goes into an error state?  That works automatically already...
Comment 7 GitLab Migration User 2018-08-25 13:53:02 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/246.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.