Chris00 / ocaml-cairo

Binding to Cairo, a 2D Vector Graphics Library.
GNU Lesser General Public License v3.0
54 stars 8 forks source link

We need better documentation of how to produce image files #4

Closed gasche closed 9 years ago

gasche commented 9 years ago

I helped a beginner trying to do some simple graphic stuff in OCaml this week-end, and the attempt to use ocaml-cairo was a total usability disaster -- Graphics is now used instead. In this issue, I'm trying to list the hurdles met along the way because I think they could all be fixed.

  1. There are two OPAM packages for cairo, cairo and cairo2, and I have no clue which one to use for which reason. You should at least be explicit in the README of this project about which of those packages you are -- cairo2. Explaining the difference between the two projects could also be very helpful.
  2. The examples/ directory is a very good idea, but currently it is very hard to use for beginners. Navigation on github is not intuitive, and there is no description of what each example does beside the filename. It would help a lot to have a list of the examples and a short description of them on the web somewhere (possibly directly in the README), maybe also showing some of the images produced by each example (but that is more work; a list would be a very good first step).
  3. There is an absolute lack of information about how to actually produce an image file. What said beginner wanted is to write a program to render Sudoku grids as images. The most important documentation for this is a code snippet that draws a rectangle and writes it in a .png file. The subject of writing image files is not discussed at all in the tutorial, and this should absolutely be fixed. What we did is to pick an example randomly (curve_to), and change it to produce a PNG instead of a PDF. You may see where this is going. We replaced Cairo.PDF.create by Cairo.PNG.create, fixed the resulting typing error in the obvious way (Cairo.PNG.create does not take dimension parameters), ran the program and got... a segfault. I was ashamed. I know this is not ocaml-cairo's fault, you bind an API in an unsafe language, but still this is quite embarrassing. This could be avoided by a comment in this example's source code that "if you want to create PNG files, see {this other example} instead" -- relatedly, a comment in diagram.ml about why the heck someone would create a SVG surface and then call Cairo.PNG.write on it could be helpful.

(Note that problem (3) is a consequence of problem (2): with clear indication of which example gives a minimum viable snippet to produce a PNG file, this whole mess would have been avoided.)

Chris00 commented 9 years ago

Thanks for trying this library!

You first point is fixed in https://github.com/Chris00/ocaml-cairo/commit/1bdcefcb8ce26074daf590bd66ad01e9b1481edb (let me know if it is not enough).

an the program and got... a segfault. I was ashamed. I know this is not ocaml-cairo's fault,

You're too kind on this one. Your program should never segfault, regardless of what you do with the (OCaml) library — and this binding is meant to exhibit this behavior.

Actually, you may be able to help me with this. I pushed a branch exn with a new (not well named) test test_create.ml. When I compile it (in custom mode as declared in _oasis) and execute it, I indeed get Segmentation fault because the registered exception is not found (caml_named_value("Cairo.Error") returns NULL). However, if I uncomment

let _ = Cairo.(Error INVALID_RESTORE)

recompile (make clean && make) and execute it again, everything works as excepted. All functions used in the code are external and it seems that then OCaml does not execute the library initialization code (toplevel let () = ...).

Chris00 commented 9 years ago

The subject of writing image files is not discussed at all in the tutorial, and this should absolutely be fixed.

It is indeed discussed indirectly. For example in the Stroke section, you can click on the image and get some code that generates a PNG. Clearly, this is not enough for newcomers. I am planning to

Would that be enough?

Chris00 commented 9 years ago

Added examples to the README a22a91c

Chris00 commented 9 years ago

Added some information for the creation of surfaces in 1d97325

Chris00 commented 9 years ago

I submitted a bug report with a minimal test case.

gasche commented 9 years ago

This is fantastic, thanks for the quick reaction. The README is much much better now, and the fact that you explicitly mention the type of files created in each example is very helpful.

Out of curiosity, why is the API for creating PNG files so different from anything else? If there was a way to also support Cairo.PNG.create fname w h with an automatic call to PNG.write at finish time, you could have a consistent description of all image formats. Of course, following the upstream API definitely has value as well. (Giving a reason for this different interfaces in the comment of 1d97325aa28e8c5505c3befb3085ec987c5ba990 could make sense.)

Sorry for the linking issue. I'm not knowledgeable in this part of the compiler, but I suspect this might be a known issue. Creating a bug report was the good thing to do anyway -- we should at least document it better, and the PR will increase awareness of the issue in any case.

gasche commented 9 years ago

I think that all the issues we encountered have been fixed, so I'm closing the PR.

Chris00 commented 9 years ago

Out of curiosity, why is the API for creating PNG files so different from anything else?

Frankly, I have no idea. With @dbuenzli, we also wondered yesterday at another inconsistency in the Cairo API (retrieving the size passed at image creation) and no rationale was found. The Cario API is not badly designed but the reason for these small inconsistencies isn't clear. Maybe I'll ask on their mailing list.

dbuenzli commented 9 years ago

Graphics is now used instead.

@gasche Since I gather you also tried Vg, any reason why this was not pursued ? (FWIW I'm currently in the process of merging a cairo2 backend, see https://github.com/dbuenzli/vg/pull/7)

gasche commented 9 years ago

I didn't try anything myself, just assisted (as lightly as possible) someone else in the process of picking a library to generate sudoku grids. Vg was not tried because at the time they were no examples easily/quickly available (I didn't insist), and Cairo proved problematic because of the issues above. In fact I was a bit disappointed that we didn't get to try Vg, because I was curious to see whether the "dbuenzli API magic" would work on relative beginners as well.

Note that Graphics had its issues as well. Graphics.set_text_size does nothing. I resorted to find an appropriately sized x11 font (you know, with charming names such as adobe-blabla-*-*-180-*-*-foo) set with set_font, and that made do for a while (I was personally horrified by the ugly bitmap rendering of oversized x11 fonts, and pushed for a vector graphics library, but the beginner did not care), and then suggested Graphicspdf for the final production of sudoku grids -- it turns out that set_text_size works, and that the output is actually quite nice.

I think that not having a PNG backend would have been perceived as an issue if we had gone the Vg route, so it's very nice that there is work towards this.

Thanks to all of you for this good work.

dbuenzli commented 9 years ago

Ok thanks for the info.

Vg was not tried because at the time they were no examples easily/quickly available (I didn't insist)

Yes the online examples are broken in some browsers at the moment, I'll try to fix that for the release. In case this happens again I'd like to mention that there are full minimal examples, compilation instructions included, in the documentation of the library.

gasche commented 9 years ago

@Chris00 , a minor thing I forgot: under Fedora, the system package to have cairo2 is named cairo-devel. It might help to put it after the Debian package name, for the (rarer) Fedora users, but also to make it clear that some systems may not have separate cairo and cairo2 packages.