Skip to content
This repository has been archived by the owner on Jun 8, 2021. It is now read-only.

Finalize PDF, SVG, PS work from #234 #236

Merged
merged 6 commits into from
Feb 10, 2019

Conversation

vojtechkral
Copy link
Contributor

Finalized the refactor and added remaining bindings for those three surface types.

Two things I'm not sure about:

  • Noticed copyrights were off, fixed it, hopefully correctly.
  • add_outline() in PDF uses bit flags. I just added integer constants that can be or'd. I thought bringing in the bitflags crate might not be appropriate.

Sorry for such a large diff.

@sdroege
Copy link
Member

sdroege commented Feb 7, 2019

@meh please review if this breaks your things :)

@@ -261,6 +265,12 @@ impl cairo_bool_t {
}
}

impl From<bool> for cairo_bool_t {
fn from(b: bool) -> cairo_bool_t {
cairo_bool_t { value: b as _ }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A match might be better, I don't think it's guaranteed that they're true = 1, false = 0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or b.to_glib() maybe? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, glib support in cairo is optional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah crap, forgot that...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok... I'd use an if here if that's ok with you...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, either way is fine :)

src/constants.rs Outdated
pub const PDF_OUTLINE_ROOT: i32 = 0;
pub const PDF_OUTLINE_OPEN: i32 = ffi::PDF_OUTLINE_FLAG_OPEN;
pub const PDF_OUTLINE_BOLD: i32 = ffi::PDF_OUTLINE_FLAG_BOLD;
pub const PDF_OUTLINE_ITALIC: i32 = ffi::PDF_OUTLINE_FLAG_ITALIC;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use bitflags for this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allright, will do...

let vers_slice = unsafe {
let mut vers_ptr: *mut ffi::cairo_pdf_version_t = mem::uninitialized();
let mut num_vers = 0;
ffi::cairo_pdf_get_versions(&mut vers_ptr as _, &mut num_vers as _);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might this return 0 or NULL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, the documentation says nothing on that and it doesn't say anything about the returned pointer memory management either. The implementation simply returns a pointer to an internal static array (see here). To be in line with that, it would probably be better to return a &str or &'static str instead of String here. (The same applies to the others.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok so can't be NULL then. Thanks for checking!

For making it a &str you need to count until the \0-terminator for each string and then use the corresponding functions, but that would indeed be nicer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is still pending from what I can see?

src/pdf.rs Outdated

pub fn set_metadata(&self, metadata: PdfMetadata, value: &str) {
unsafe {
ffi::cairo_pdf_surface_set_metadata(self.inner.to_raw_none(), metadata.into(), value.as_ptr() as _);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work (in general). &str is not \0-terminated so you can't just use as_ptr() on it like this.

There's CStr / CString for working with this correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the whole cairo codebase for this while you're at it, and also especially the code of your previews PR :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

let lvls_slice = unsafe {
let mut vers_ptr: *mut ffi::cairo_ps_level_t = mem::uninitialized();
let mut num_vers = 0;
ffi::cairo_ps_get_levels(&mut vers_ptr as _, &mut num_vers as _);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this return 0 / NULL?

let vers_slice = unsafe {
let mut vers_ptr: *mut ffi::cairo_svg_version_t = mem::uninitialized();
let mut num_vers = 0;
ffi::cairo_svg_get_versions(&mut vers_ptr as _, &mut num_vers as _);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And how about this? :)

@vojtechkral
Copy link
Contributor Author

Updated

@meh
Copy link
Contributor

meh commented Feb 7, 2019

I have some slight concerns still with the removal of the Buffer crap, but I think it's doable with Writer::finish anyway, so whatever.

@sdroege
Copy link
Member

sdroege commented Feb 7, 2019

I have some slight concerns still with the removal of the Buffer crap, but I think it's doable with Writer::finish anyway, so whatever.

So does it work for your use-case or is more work needed? :)

unsafe {
let res = ffi::cairo_pdf_version_to_string(version.into());
res.as_ref().and_then(|cstr| CStr::from_ptr(cstr as _).to_str().ok()).map(String::from)
res.as_ref().and_then(|cstr| CStr::from_ptr(cstr as _).to_str().ok())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the C function ever return NULL? If not then this function should never return None. If the string stuff fails you can safely assert here (expect()). Stuff is all lost then anyway :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing for any other function like this. IIRC there was also one for SVG here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does return NULL if the version argument is not one of the defined values, which the bindings in enum.rs generally don't protect against (ie. there's the __Unknown(i32) variant). I suppose the enum could be made exhaustive and there could be an assert in it's from From<ffi:: ... > implementation. Then this could simplified. I don't have a strong feeling one way or the other, feel free to pick whichever you think is right...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It even mentions in the docs of that function that it can return NULL, so this is fine then.

@vojtechkral
Copy link
Contributor Author

vojtechkral commented Feb 8, 2019

@meh

I have some slight concerns still with the removal of the Buffer crap, but I think it's doable with Writer::finish anyway, so whatever.

I'd like to improve the ergonomics if I can. Feel free to post usage example of Buffer vs Writer or something. Would an ability to reference the io::Write object while the Writer is still in scope help you? I think that could be done and I had been thinking about adding that one anyway...

Edit: In fact, I think the Writer could even blanket-impl some of the Buffer methods for io::Writers that are also Deref<Target = [u8]>, which is the case of Vec<u8>. I'll look into it.

@meh
Copy link
Contributor

meh commented Feb 8, 2019

I have some slight concerns still with the removal of the Buffer crap, but I think it's doable with Writer::finish anyway, so whatever.

So does it work for your use-case or is more work needed? :)

It works for the current use case, my only concern is when we need to start sending PDFs through HTTP responses and such.

I honestly don't remember why I wanted to be able to access a pdf::Buffer through AsRef<[u8]>, so using finish() and sending the buffer through might be enough.

Only time will tell.

@sdroege
Copy link
Member

sdroege commented Feb 8, 2019

@meh what you're missing is a way to incrementally write things instead of having the whole thing in memory at once?

@vojtechkral
Copy link
Contributor Author

I added the AsRef<[u8]> and writer() + writer_mut() for convenience.

@sdroege
Copy link
Member

sdroege commented Feb 10, 2019

@GuillaumeGomez Let get this in then?

@GuillaumeGomez
Copy link
Member

Thanks @vojtechkral !

@GuillaumeGomez GuillaumeGomez merged commit fb6df64 into gtk-rs:master Feb 10, 2019
@vojtechkral
Copy link
Contributor Author

Thank you all for bearing with me through this :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants