Open MaximeBouton opened 4 years ago
What are you trying to do? The logic of libcairo is, that you decide the type of surface before starting to draw and to render. If you are looking for a lazy/late decision, you might look at recordingSurfaces. btw: the non-stream (with filename) surface constructors still exist (although libcairo documentation discourages the use).
We have a visualization package that relies on Cairo: https://github.com/sisl/AutoViz.jl
The main usage is through a render function, that accepts a CairoSurface
as keyword argument (default to CairoSVGSurface
).
Now we would like users to be able to save the rendered scenes in different format using write
.
If they want a PDF they would have to pass in a CairoPDFSurface
to the function which is fine, but we were wondering if there was a way to warn user when they try to do something like this:
c = render([roadway, veh1, veh2], camera=CarFollowCamera(...)) # default to SVGSurface
write("scene.pdf", c)
This code will run fine but the user might think they have a pdf and instead they have an svg.
The correct way would have been to do:
c = render([roadway, veh1, veh2], camera=CarFollowCamera(...), surface=CairoPDFSurface(...))
write("scene.pdf", c)
I see. a) One could get the 'type' of a surface by looking via the surface type ptr into the c-struct of a cairo surface i.e.
struct _cairo_surface {
const cairo_surface_backend_t *backend;
cairo_device_t *device;
/* We allow surfaces to override the backend->type by shoving something
* else into surface->type. This is for "wrapper" surfaces that want to
* hide their internal type from the user-level API. */
cairo_surface_type_t type;
cairo_content_t content;
cairo_reference_count_t ref_count;
cairo_status_t status;
b) workaround could be to look at the actual stream, as both PDF and SVG have headers (files need to start with a sequence of know bytes)
c) take the information along your 'c' output (type) of the render function. d) ... as someone not believing in file extensions -> you cannot avoid users to do wrong.
Thanks for the tips, I will give a shot to a)!
this worked:
typ = ccall((:cairo_surface_get_type, Cairo.libcairo), Cint, (Ptr{Nothing},), c.ptr)
if typ == Cairo.CAIRO_SURFACE_TYPE_PDF
# do stuff
end
Thanks!
When trying to write a cairo surface to a file, it is not possible to distinguish whether the surface object is a pdf or svg surface.
MWE:
Is there a convenient way to enforce that the file extension matches the type of Cairo stream? Right now both CairoSVGSurface and CairoPDFSurface outputs a CairoSurfaceIOStream which makes it not possible to dispatch between the two.