[cairo] On fallback strategies (was Re: GSoC: Scan converting rasteriser update

Jeff Muizelaar jeff at infidigm.net
Sat Oct 18 13:07:02 PDT 2008

On Sat, Oct 18, 2008 at 02:52:40PM -0400, Behdad Esfahbod wrote:
> Jeff Muizelaar wrote:
> > The UNSUPPORTED model becomes problematic as soon as a backend wants to
> > implement one of these methods previously unimplemented methods.
> > Fallbacks are a all-or-nothing choice, so implementing anything that
> > uses some of the previous fallback is difficult. This makes adjusting
> > the behaviour of a fallback difficult for a backend.
> Using UNSUPPORTED does not mean we can't have
> _cairo_image_fallback_do_some_part_of_filling_and_just_that().
> It's not either/or.  Define UNSUPPORTED as calling cairo_surface_fallback_XXX().

I agree. I just wanted some consensus about UNSUPPORTED not always being
the right thing to do, especially when different backends want to
implement an operation in different ways.

> > Further, I don't see why one would have to copy paste a lot of cruft
> > when we can have a utility function that's called. There's no reason a
> > fill() implementation would need to be anything more than a single
> > function call.
> I'm talking about that single-line function that needs to be copied in 12
> different backend files, and modified every time the backend signature changes.

I'd gladly trade that for greater code readability. I read the code more
often then the backend signature changes and I don't see the duplication
being a source of bugs. But I do agree, if we end up in a sitatuation
like you describe, something's wrong.

> > That's not really true; you do need to worry about what happens. If you
> > have a backend that doesn't implement fill() you have to implement
> > composite_trapezoids(). composite_trapezoids() certainly isn't the only
> > logical operation to implement fill with, a backend end could, for
> > example, want composite_spans(), composite_flattened_polygon() or
> > composite_non_intersecting_polygon(). We wouldn't want to probe each
> > backend for each of these possible operations. 
> Sure, some operations may be better fallbacked using a function calling helper
> functions.  But for show_glyphs for example, there's no way to do it cleaner
> than using UNSUPPORTED.  The way it works currently is:
> cairo_surface_show_glyphs:
> 	try surface_backend->show_glyphs
> 	cairo_surface_fallback_show_glyphs
> 		cairo_scaled_font_show_glyphs
> 			try font_backend->show_glyphs
> 			create a mask, add glyphs to it and paint it

I don't advocate eliminating the UNSUPPORTED idiom entirely. If it makes
more sense for an operation to return UNSUPPORTED then we should
certainly keep it. I don't want to be dogmatic about it. Right now I
mostly care about fill() and stroke() and don't think the fallback
structure makes sense for backends that aren't XRender-like. I haven't
really thought about the other operations much yet. 

> Currently the backend interface has like 15 methods, many backends implement
> only five of them.  How does adding ten one-line functions make it more readable?

One of the things it could potentially do is eliminate is some of the backend
interface methods. For example, fill_rectangles() and
composite_trapezoids() could go away. However, I too don't want to end
up in a situation where a backend has to implement ten one-line

Any changes related to this should be gradual, so we should be able to
evaluate each circumstance as needed.


More information about the cairo mailing list