[cairo] Cairo and ISO C++

Uli Schlachter psychon at znc.in
Tue Jan 21 13:04:12 PST 2014


On 21.01.2014 01:16, Michael McLaughlin wrote:
> I wanted to give everyone an update. Earlier today a proposal that Herb,
> Jason, and I have been working on, N3888: A Proposal to Add 2D Graphics
> Rendering and Display to C++, was published here:
> http://isocpp.org/files/papers/N3888.pdf . The main focus of the proposal
> is a series of rules that enable a mechanical transformation from the cairo
> API to an API that is in the style of the C++ Standard Library (the STL).

I skimmed the PDF and some things in VII.A made me wonder:

The image_surface class has the following constructor and member functions:

image_surface(::std::vector<unsigned char>& data, format format, int width, int
height, int stride);
void set_data(::std::vector<unsigned char>& data);
::std::vector<unsigned char> get_data();

These functions are obviously the transformations for
cairo_image_surface_create_for_data() and cairo_image_surface_get_data() (And
set_data() is a new invention for which I cannot find any transformation
explaining it).

What exactly are the semantics of these functions? Cairo's _for_data()
constructor doesn't create a copy of the data that it receives, but works on the
memory buffer that it received. This pointer is then also returned from _get_data().

However, this C++ API obviously has to make a copy of the data in both
get_data() and set_data(). So basically "cheap" access/modifying of an image
surface's pixel data is not possible through this API.

What's the reasoning behind this?

I would have expected a mapping from cairo's _get_data() to something like
::std::vector<unsigned char>& get_data(), but this obviously leaks quite some
implementation details from the C++ API...

Also, the following constructor is IMO quite ugly:

image_surface(const ::std::string& filename);
::std::function<void(void* closure,
::std::vector<unsigned char>& data)> read_fn, void* closure);

This must be coming from cairo_image_surface_create_from_png{,_stream}(), but I
only guess so from the arguments. Nothing in the function really mentions PNGs.
It might be nicer to have static factory functions for these, just so that the
name "PNG" can be given.

How does the user_data API work? With cairo, we have a function pointer to a
destroy function. This seems to be replaced by ::std::shared_ptr<void>&. I admit
that my C++ might be a little rusty, but is this an adequate replacement? This
keeps a void* around which will be deleted when needed. However, since void*
doesn't have a virtual destructor, I cannot really use this to do the same
things that I can do with cairo (= run arbitrary code of my own).

void gradient_pattern::get_color_stop_count(int& count);
void surface_pattern::get_surface(surface& s);
Shouldn't this just return an int / a surface?

void surface::get_fallback_resolution(double& x_pixels_per_inch,
double& y_pixels_per_inch); seems like a candidate for returning a
std::pair<double, double>, although I have to admit that this loses some

linear_pattern(double x0, double y0, double x1, double y1);
It might make sense to represent points as std::pair<double, double>, but I am
not sure how much sense this really makes (nor how many places this would affect
nor how this could be done via a "simple" transformation).

"For saving the Earth.. and eating cheesecake!"

More information about the cairo mailing list